Skip to content

Commit 6f4e10d

Browse files
qizhangzmergify[bot]
authored andcommitted
SecurityPkg: Add retry mechanism for tpm command
REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3980 As per TCG PC Client Device Driver Design Principle document, if tpm commands fails due to timeout condition, then it should have retry mechanism (3 retry attempts). Existing implementation of PtpCrbTpmCommand does not have retry mechanism if it fails with EFI_TIMEOUT. See TCG PC Client Device Driver Design Principles for TPM 2.0 https://trustedcomputinggroup.org/wp-content/uploads/TCG_PCClient_Device_Driver_Design_Principles_TPM2p0_v1p1_r4_211104_final.pdf Vision 1.1, Revision 0.04 Section 7.2.1 Signed-off-by: Qi Zhang <[email protected]> Cc: Jiewen Yao <[email protected]> Cc: Jian J Wang <[email protected]> Reviewed-by: Jiewen Yao <[email protected]> Tested-by: Swapnil Patil <[email protected]>
1 parent e915061 commit 6f4e10d

File tree

1 file changed

+69
-39
lines changed
  • SecurityPkg/Library/Tpm2DeviceLibDTpm

1 file changed

+69
-39
lines changed

SecurityPkg/Library/Tpm2DeviceLibDTpm/Tpm2Ptp.c

+69-39
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,12 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
3333
//
3434
#define TPMCMDBUFLENGTH 0x500
3535

36+
//
37+
// Max retry count according to Spec TCG PC Client Device Driver Design Principles
38+
// for TPM2.0, Version 1.1, Revision 0.04, Section 7.2.1
39+
//
40+
#define RETRY_CNT_MAX 3
41+
3642
/**
3743
Check whether TPM PTP register exist.
3844
@@ -153,6 +159,7 @@ PtpCrbTpmCommand (
153159
UINT32 TpmOutSize;
154160
UINT16 Data16;
155161
UINT32 Data32;
162+
UINT8 RetryCnt;
156163

157164
DEBUG_CODE_BEGIN ();
158165
UINTN DebugSize;
@@ -179,53 +186,76 @@ PtpCrbTpmCommand (
179186
DEBUG_CODE_END ();
180187
TpmOutSize = 0;
181188

182-
//
183-
// STEP 0:
184-
// if CapCRbIdelByPass == 0, enforce Idle state before sending command
185-
//
186-
if ((GetCachedIdleByPass () == 0) && ((MmioRead32 ((UINTN)&CrbReg->CrbControlStatus) & PTP_CRB_CONTROL_AREA_STATUS_TPM_IDLE) == 0)) {
189+
RetryCnt = 0;
190+
while (TRUE) {
191+
//
192+
// STEP 0:
193+
// if CapCRbIdelByPass == 0, enforce Idle state before sending command
194+
//
195+
if ((GetCachedIdleByPass () == 0) && ((MmioRead32 ((UINTN)&CrbReg->CrbControlStatus) & PTP_CRB_CONTROL_AREA_STATUS_TPM_IDLE) == 0)) {
196+
Status = PtpCrbWaitRegisterBits (
197+
&CrbReg->CrbControlStatus,
198+
PTP_CRB_CONTROL_AREA_STATUS_TPM_IDLE,
199+
0,
200+
PTP_TIMEOUT_C
201+
);
202+
if (EFI_ERROR (Status)) {
203+
RetryCnt++;
204+
if (RetryCnt < RETRY_CNT_MAX) {
205+
MmioWrite32 ((UINTN)&CrbReg->CrbControlRequest, PTP_CRB_CONTROL_AREA_REQUEST_GO_IDLE);
206+
continue;
207+
} else {
208+
//
209+
// Try to goIdle to recover TPM
210+
//
211+
Status = EFI_DEVICE_ERROR;
212+
goto GoIdle_Exit;
213+
}
214+
}
215+
}
216+
217+
//
218+
// STEP 1:
219+
// Ready is any time the TPM is ready to receive a command, following a write
220+
// of 1 by software to Request.cmdReady, as indicated by the Status field
221+
// being cleared to 0.
222+
//
223+
MmioWrite32 ((UINTN)&CrbReg->CrbControlRequest, PTP_CRB_CONTROL_AREA_REQUEST_COMMAND_READY);
187224
Status = PtpCrbWaitRegisterBits (
188-
&CrbReg->CrbControlStatus,
189-
PTP_CRB_CONTROL_AREA_STATUS_TPM_IDLE,
225+
&CrbReg->CrbControlRequest,
190226
0,
227+
PTP_CRB_CONTROL_AREA_REQUEST_COMMAND_READY,
191228
PTP_TIMEOUT_C
192229
);
193230
if (EFI_ERROR (Status)) {
194-
//
195-
// Try to goIdle to recover TPM
196-
//
197-
Status = EFI_DEVICE_ERROR;
198-
goto GoIdle_Exit;
231+
RetryCnt++;
232+
if (RetryCnt < RETRY_CNT_MAX) {
233+
MmioWrite32 ((UINTN)&CrbReg->CrbControlRequest, PTP_CRB_CONTROL_AREA_REQUEST_GO_IDLE);
234+
continue;
235+
} else {
236+
Status = EFI_DEVICE_ERROR;
237+
goto GoIdle_Exit;
238+
}
199239
}
200-
}
201240

202-
//
203-
// STEP 1:
204-
// Ready is any time the TPM is ready to receive a command, following a write
205-
// of 1 by software to Request.cmdReady, as indicated by the Status field
206-
// being cleared to 0.
207-
//
208-
MmioWrite32 ((UINTN)&CrbReg->CrbControlRequest, PTP_CRB_CONTROL_AREA_REQUEST_COMMAND_READY);
209-
Status = PtpCrbWaitRegisterBits (
210-
&CrbReg->CrbControlRequest,
211-
0,
212-
PTP_CRB_CONTROL_AREA_REQUEST_COMMAND_READY,
213-
PTP_TIMEOUT_C
214-
);
215-
if (EFI_ERROR (Status)) {
216-
Status = EFI_DEVICE_ERROR;
217-
goto GoIdle_Exit;
218-
}
241+
Status = PtpCrbWaitRegisterBits (
242+
&CrbReg->CrbControlStatus,
243+
0,
244+
PTP_CRB_CONTROL_AREA_STATUS_TPM_IDLE,
245+
PTP_TIMEOUT_C
246+
);
247+
if (EFI_ERROR (Status)) {
248+
RetryCnt++;
249+
if (RetryCnt < RETRY_CNT_MAX) {
250+
MmioWrite32 ((UINTN)&CrbReg->CrbControlRequest, PTP_CRB_CONTROL_AREA_REQUEST_GO_IDLE);
251+
continue;
252+
} else {
253+
Status = EFI_DEVICE_ERROR;
254+
goto GoIdle_Exit;
255+
}
256+
}
219257

220-
Status = PtpCrbWaitRegisterBits (
221-
&CrbReg->CrbControlStatus,
222-
0,
223-
PTP_CRB_CONTROL_AREA_STATUS_TPM_IDLE,
224-
PTP_TIMEOUT_C
225-
);
226-
if (EFI_ERROR (Status)) {
227-
Status = EFI_DEVICE_ERROR;
228-
goto GoIdle_Exit;
258+
break;
229259
}
230260

231261
//

0 commit comments

Comments
 (0)