]> git.proxmox.com Git - mirror_edk2.git/blame - SecurityPkg/Library/Tpm12DeviceLibDTpm/Tpm12Tis.c
UefiCpuPkg: Move AsmRelocateApLoopStart from Mpfuncs.nasm to AmdSev.nasm
[mirror_edk2.git] / SecurityPkg / Library / Tpm12DeviceLibDTpm / Tpm12Tis.c
CommitLineData
c1d93242
JY
1/** @file\r
2 TIS (TPM Interface Specification) functions used by TPM1.2.\r
b3548d32
LG
3\r
4Copyright (c) 2013 - 2018, Intel Corporation. All rights reserved.<BR>\r
6aaac383 5(C) Copyright 2015 Hewlett Packard Enterprise Development LP<BR>\r
289b714b 6SPDX-License-Identifier: BSD-2-Clause-Patent\r
c1d93242
JY
7\r
8**/\r
9\r
10#include <Uefi.h>\r
11#include <IndustryStandard/Tpm12.h>\r
12#include <Library/BaseLib.h>\r
13#include <Library/BaseMemoryLib.h>\r
14#include <Library/IoLib.h>\r
15#include <Library/TimerLib.h>\r
16#include <Library/DebugLib.h>\r
17#include <Library/Tpm12CommandLib.h>\r
18#include <Library/PcdLib.h>\r
19\r
8e997ab8
JY
20#include <IndustryStandard/TpmPtp.h>\r
21#include <IndustryStandard/TpmTis.h>\r
c1d93242 22\r
8e997ab8
JY
23typedef enum {\r
24 PtpInterfaceTis,\r
25 PtpInterfaceFifo,\r
26 PtpInterfaceCrb,\r
27 PtpInterfaceMax,\r
28} PTP_INTERFACE_TYPE;\r
c1d93242
JY
29\r
30//\r
f9fd0c21 31// Max TPM command/response length\r
c1d93242 32//\r
c411b485 33#define TPMCMDBUFLENGTH 1024\r
c1d93242
JY
34\r
35/**\r
36 Check whether TPM chip exist.\r
37\r
38 @param[in] TisReg Pointer to TIS register.\r
39\r
40 @retval TRUE TPM chip exists.\r
41 @retval FALSE TPM chip is not found.\r
42**/\r
43BOOLEAN\r
44Tpm12TisPcPresenceCheck (\r
c411b485 45 IN TIS_PC_REGISTERS_PTR TisReg\r
c1d93242
JY
46 )\r
47{\r
c411b485 48 UINT8 RegRead;\r
b3548d32 49\r
c1d93242
JY
50 RegRead = MmioRead8 ((UINTN)&TisReg->Access);\r
51 return (BOOLEAN)(RegRead != (UINT8)-1);\r
52}\r
53\r
e4780913
JY
54/**\r
55 Return PTP interface type.\r
56\r
57 @param[in] Register Pointer to PTP register.\r
58\r
59 @return PTP interface type.\r
60**/\r
61PTP_INTERFACE_TYPE\r
62Tpm12GetPtpInterface (\r
c411b485 63 IN VOID *Register\r
e4780913
JY
64 )\r
65{\r
c411b485
MK
66 PTP_CRB_INTERFACE_IDENTIFIER InterfaceId;\r
67 PTP_FIFO_INTERFACE_CAPABILITY InterfaceCapability;\r
e4780913
JY
68\r
69 if (!Tpm12TisPcPresenceCheck (Register)) {\r
70 return PtpInterfaceMax;\r
71 }\r
c411b485 72\r
e4780913
JY
73 //\r
74 // Check interface id\r
75 //\r
c411b485 76 InterfaceId.Uint32 = MmioRead32 ((UINTN)&((PTP_CRB_REGISTERS *)Register)->InterfaceId);\r
e4780913
JY
77 InterfaceCapability.Uint32 = MmioRead32 ((UINTN)&((PTP_FIFO_REGISTERS *)Register)->InterfaceCapability);\r
78\r
79 if ((InterfaceId.Bits.InterfaceType == PTP_INTERFACE_IDENTIFIER_INTERFACE_TYPE_CRB) &&\r
80 (InterfaceId.Bits.InterfaceVersion == PTP_INTERFACE_IDENTIFIER_INTERFACE_VERSION_CRB) &&\r
c411b485
MK
81 (InterfaceId.Bits.CapCRB != 0))\r
82 {\r
e4780913
JY
83 return PtpInterfaceCrb;\r
84 }\r
c411b485 85\r
e4780913
JY
86 if ((InterfaceId.Bits.InterfaceType == PTP_INTERFACE_IDENTIFIER_INTERFACE_TYPE_FIFO) &&\r
87 (InterfaceId.Bits.InterfaceVersion == PTP_INTERFACE_IDENTIFIER_INTERFACE_VERSION_FIFO) &&\r
88 (InterfaceId.Bits.CapFIFO != 0) &&\r
c411b485
MK
89 (InterfaceCapability.Bits.InterfaceVersion == INTERFACE_CAPABILITY_INTERFACE_VERSION_PTP))\r
90 {\r
e4780913
JY
91 return PtpInterfaceFifo;\r
92 }\r
c411b485 93\r
e4780913
JY
94 return PtpInterfaceTis;\r
95}\r
96\r
c1d93242
JY
97/**\r
98 Check whether the value of a TPM chip register satisfies the input BIT setting.\r
99\r
100 @param[in] Register Address port of register to be checked.\r
101 @param[in] BitSet Check these data bits are set.\r
102 @param[in] BitClear Check these data bits are clear.\r
103 @param[in] TimeOut The max wait time (unit MicroSecond) when checking register.\r
104\r
105 @retval EFI_SUCCESS The register satisfies the check bit.\r
106 @retval EFI_TIMEOUT The register can't run into the expected status in time.\r
107**/\r
108EFI_STATUS\r
c1d93242 109Tpm12TisPcWaitRegisterBits (\r
c411b485
MK
110 IN UINT8 *Register,\r
111 IN UINT8 BitSet,\r
112 IN UINT8 BitClear,\r
113 IN UINT32 TimeOut\r
c1d93242
JY
114 )\r
115{\r
c411b485
MK
116 UINT8 RegRead;\r
117 UINT32 WaitTime;\r
c1d93242 118\r
c411b485 119 for (WaitTime = 0; WaitTime < TimeOut; WaitTime += 30) {\r
c1d93242 120 RegRead = MmioRead8 ((UINTN)Register);\r
c411b485 121 if (((RegRead & BitSet) == BitSet) && ((RegRead & BitClear) == 0)) {\r
c1d93242 122 return EFI_SUCCESS;\r
c411b485
MK
123 }\r
124\r
c1d93242
JY
125 MicroSecondDelay (30);\r
126 }\r
c411b485 127\r
c1d93242
JY
128 return EFI_TIMEOUT;\r
129}\r
130\r
131/**\r
f9fd0c21 132 Get BurstCount by reading the burstCount field of a TIS register\r
c1d93242
JY
133 in the time of default TIS_TIMEOUT_D.\r
134\r
135 @param[in] TisReg Pointer to TIS register.\r
d6b926e7 136 @param[out] BurstCount Pointer to a buffer to store the got BurstCount.\r
c1d93242
JY
137\r
138 @retval EFI_SUCCESS Get BurstCount.\r
139 @retval EFI_INVALID_PARAMETER TisReg is NULL or BurstCount is NULL.\r
140 @retval EFI_TIMEOUT BurstCount can't be got in time.\r
141**/\r
142EFI_STATUS\r
c1d93242 143Tpm12TisPcReadBurstCount (\r
c411b485
MK
144 IN TIS_PC_REGISTERS_PTR TisReg,\r
145 OUT UINT16 *BurstCount\r
c1d93242
JY
146 )\r
147{\r
c411b485
MK
148 UINT32 WaitTime;\r
149 UINT8 DataByte0;\r
150 UINT8 DataByte1;\r
c1d93242 151\r
c411b485 152 if ((BurstCount == NULL) || (TisReg == NULL)) {\r
c1d93242
JY
153 return EFI_INVALID_PARAMETER;\r
154 }\r
155\r
156 WaitTime = 0;\r
157 do {\r
158 //\r
159 // TIS_PC_REGISTERS_PTR->burstCount is UINT16, but it is not 2bytes aligned,\r
160 // so it needs to use MmioRead8 to read two times\r
161 //\r
162 DataByte0 = MmioRead8 ((UINTN)&TisReg->BurstCount);\r
163 DataByte1 = MmioRead8 ((UINTN)&TisReg->BurstCount + 1);\r
164 *BurstCount = (UINT16)((DataByte1 << 8) + DataByte0);\r
165 if (*BurstCount != 0) {\r
166 return EFI_SUCCESS;\r
167 }\r
c411b485 168\r
c1d93242
JY
169 MicroSecondDelay (30);\r
170 WaitTime += 30;\r
171 } while (WaitTime < TIS_TIMEOUT_D);\r
172\r
173 return EFI_TIMEOUT;\r
174}\r
175\r
176/**\r
b3548d32 177 Set TPM chip to ready state by sending ready command TIS_PC_STS_READY\r
c1d93242
JY
178 to Status Register in time.\r
179\r
180 @param[in] TisReg Pointer to TIS register.\r
181\r
182 @retval EFI_SUCCESS TPM chip enters into ready state.\r
183 @retval EFI_INVALID_PARAMETER TisReg is NULL.\r
184 @retval EFI_TIMEOUT TPM chip can't be set to ready state in time.\r
185**/\r
186EFI_STATUS\r
c1d93242 187Tpm12TisPcPrepareCommand (\r
c411b485 188 IN TIS_PC_REGISTERS_PTR TisReg\r
c1d93242
JY
189 )\r
190{\r
c411b485 191 EFI_STATUS Status;\r
c1d93242
JY
192\r
193 if (TisReg == NULL) {\r
194 return EFI_INVALID_PARAMETER;\r
195 }\r
196\r
c411b485 197 MmioWrite8 ((UINTN)&TisReg->Status, TIS_PC_STS_READY);\r
c1d93242
JY
198 Status = Tpm12TisPcWaitRegisterBits (\r
199 &TisReg->Status,\r
200 TIS_PC_STS_READY,\r
201 0,\r
202 TIS_TIMEOUT_B\r
203 );\r
204 return Status;\r
205}\r
206\r
207/**\r
b3548d32 208 Get the control of TPM chip by sending requestUse command TIS_PC_ACC_RQUUSE\r
c1d93242
JY
209 to ACCESS Register in the time of default TIS_TIMEOUT_A.\r
210\r
211 @param[in] TisReg Pointer to TIS register.\r
212\r
213 @retval EFI_SUCCESS Get the control of TPM chip.\r
214 @retval EFI_INVALID_PARAMETER TisReg is NULL.\r
215 @retval EFI_NOT_FOUND TPM chip doesn't exit.\r
216 @retval EFI_TIMEOUT Can't get the TPM control in time.\r
217**/\r
218EFI_STATUS\r
c1d93242 219Tpm12TisPcRequestUseTpm (\r
c411b485 220 IN TIS_PC_REGISTERS_PTR TisReg\r
c1d93242
JY
221 )\r
222{\r
c411b485 223 EFI_STATUS Status;\r
b3548d32 224\r
c1d93242
JY
225 if (TisReg == NULL) {\r
226 return EFI_INVALID_PARAMETER;\r
227 }\r
b3548d32 228\r
c1d93242
JY
229 if (!Tpm12TisPcPresenceCheck (TisReg)) {\r
230 return EFI_NOT_FOUND;\r
231 }\r
232\r
c411b485 233 MmioWrite8 ((UINTN)&TisReg->Access, TIS_PC_ACC_RQUUSE);\r
c1d93242
JY
234 Status = Tpm12TisPcWaitRegisterBits (\r
235 &TisReg->Access,\r
236 (UINT8)(TIS_PC_ACC_ACTIVE |TIS_PC_VALID),\r
237 0,\r
238 TIS_TIMEOUT_A\r
239 );\r
240 return Status;\r
241}\r
242\r
243/**\r
244 Send a command to TPM for execution and return response data.\r
245\r
b3548d32
LG
246 @param[in] TisReg TPM register space base address.\r
247 @param[in] BufferIn Buffer for command data.\r
248 @param[in] SizeIn Size of command data.\r
249 @param[in, out] BufferOut Buffer for response data.\r
250 @param[in, out] SizeOut Size of response data.\r
251\r
c1d93242 252 @retval EFI_SUCCESS Operation completed successfully.\r
c1d93242
JY
253 @retval EFI_BUFFER_TOO_SMALL Response data buffer is too small.\r
254 @retval EFI_DEVICE_ERROR Unexpected device behavior.\r
255 @retval EFI_UNSUPPORTED Unsupported TPM version\r
256\r
257**/\r
258EFI_STATUS\r
259Tpm12TisTpmCommand (\r
c411b485
MK
260 IN TIS_PC_REGISTERS_PTR TisReg,\r
261 IN UINT8 *BufferIn,\r
262 IN UINT32 SizeIn,\r
263 IN OUT UINT8 *BufferOut,\r
264 IN OUT UINT32 *SizeOut\r
c1d93242
JY
265 )\r
266{\r
c411b485
MK
267 EFI_STATUS Status;\r
268 UINT16 BurstCount;\r
269 UINT32 Index;\r
270 UINT32 TpmOutSize;\r
271 UINT16 Data16;\r
272 UINT32 Data32;\r
273 UINT16 RspTag;\r
c1d93242 274\r
f9f4fb23 275 DEBUG_CODE_BEGIN ();\r
c411b485 276 UINTN DebugSize;\r
c1d93242 277\r
c411b485
MK
278 DEBUG ((DEBUG_VERBOSE, "Tpm12TisTpmCommand Send - "));\r
279 if (SizeIn > 0x100) {\r
280 DebugSize = 0x40;\r
281 } else {\r
282 DebugSize = SizeIn;\r
283 }\r
284\r
285 for (Index = 0; Index < DebugSize; Index++) {\r
286 DEBUG ((DEBUG_VERBOSE, "%02x ", BufferIn[Index]));\r
287 }\r
288\r
289 if (DebugSize != SizeIn) {\r
290 DEBUG ((DEBUG_VERBOSE, "...... "));\r
291 for (Index = SizeIn - 0x20; Index < SizeIn; Index++) {\r
e905fbb0 292 DEBUG ((DEBUG_VERBOSE, "%02x ", BufferIn[Index]));\r
c1d93242 293 }\r
c411b485
MK
294 }\r
295\r
296 DEBUG ((DEBUG_VERBOSE, "\n"));\r
f9f4fb23 297 DEBUG_CODE_END ();\r
c1d93242
JY
298 TpmOutSize = 0;\r
299\r
300 Status = Tpm12TisPcPrepareCommand (TisReg);\r
c411b485 301 if (EFI_ERROR (Status)) {\r
c1d93242 302 DEBUG ((DEBUG_ERROR, "Tpm12 is not ready for command!\n"));\r
6f785cfc 303 return EFI_DEVICE_ERROR;\r
c1d93242 304 }\r
c411b485 305\r
c1d93242
JY
306 //\r
307 // Send the command data to Tpm\r
308 //\r
309 Index = 0;\r
310 while (Index < SizeIn) {\r
311 Status = Tpm12TisPcReadBurstCount (TisReg, &BurstCount);\r
312 if (EFI_ERROR (Status)) {\r
6f785cfc 313 Status = EFI_DEVICE_ERROR;\r
c1d93242
JY
314 goto Exit;\r
315 }\r
c411b485
MK
316\r
317 for ( ; BurstCount > 0 && Index < SizeIn; BurstCount--) {\r
318 MmioWrite8 ((UINTN)&TisReg->DataFifo, *(BufferIn + Index));\r
c1d93242
JY
319 Index++;\r
320 }\r
321 }\r
c411b485 322\r
c1d93242
JY
323 //\r
324 // Check the Tpm status STS_EXPECT change from 1 to 0\r
325 //\r
326 Status = Tpm12TisPcWaitRegisterBits (\r
327 &TisReg->Status,\r
c411b485 328 (UINT8)TIS_PC_VALID,\r
c1d93242
JY
329 TIS_PC_STS_EXPECT,\r
330 TIS_TIMEOUT_C\r
331 );\r
332 if (EFI_ERROR (Status)) {\r
333 DEBUG ((DEBUG_ERROR, "Tpm12 The send buffer too small!\n"));\r
334 Status = EFI_BUFFER_TOO_SMALL;\r
335 goto Exit;\r
336 }\r
c411b485 337\r
c1d93242
JY
338 //\r
339 // Executed the TPM command and waiting for the response data ready\r
340 //\r
c411b485 341 MmioWrite8 ((UINTN)&TisReg->Status, TIS_PC_STS_GO);\r
c1d93242
JY
342 Status = Tpm12TisPcWaitRegisterBits (\r
343 &TisReg->Status,\r
c411b485 344 (UINT8)(TIS_PC_VALID | TIS_PC_STS_DATA),\r
c1d93242
JY
345 0,\r
346 TIS_TIMEOUT_B\r
347 );\r
348 if (EFI_ERROR (Status)) {\r
349 DEBUG ((DEBUG_ERROR, "Wait for Tpm12 response data time out!!\n"));\r
6f785cfc 350 Status = EFI_DEVICE_ERROR;\r
c1d93242
JY
351 goto Exit;\r
352 }\r
c411b485 353\r
c1d93242
JY
354 //\r
355 // Get response data header\r
356 //\r
c411b485 357 Index = 0;\r
c1d93242
JY
358 BurstCount = 0;\r
359 while (Index < sizeof (TPM_RSP_COMMAND_HDR)) {\r
360 Status = Tpm12TisPcReadBurstCount (TisReg, &BurstCount);\r
361 if (EFI_ERROR (Status)) {\r
6f785cfc 362 Status = EFI_DEVICE_ERROR;\r
c1d93242
JY
363 goto Exit;\r
364 }\r
c411b485
MK
365\r
366 for ( ; BurstCount > 0; BurstCount--) {\r
c1d93242
JY
367 *(BufferOut + Index) = MmioRead8 ((UINTN)&TisReg->DataFifo);\r
368 Index++;\r
c411b485
MK
369 if (Index == sizeof (TPM_RSP_COMMAND_HDR)) {\r
370 break;\r
371 }\r
c1d93242
JY
372 }\r
373 }\r
c411b485 374\r
f9f4fb23 375 DEBUG_CODE_BEGIN ();\r
c411b485
MK
376 DEBUG ((DEBUG_VERBOSE, "Tpm12TisTpmCommand ReceiveHeader - "));\r
377 for (Index = 0; Index < sizeof (TPM_RSP_COMMAND_HDR); Index++) {\r
378 DEBUG ((DEBUG_VERBOSE, "%02x ", BufferOut[Index]));\r
379 }\r
380\r
381 DEBUG ((DEBUG_VERBOSE, "\n"));\r
f9f4fb23 382 DEBUG_CODE_END ();\r
c1d93242 383 //\r
ee46ac08 384 // Check the response data header (tag, parasize and returncode)\r
c1d93242
JY
385 //\r
386 CopyMem (&Data16, BufferOut, sizeof (UINT16));\r
ee46ac08 387 RspTag = SwapBytes16 (Data16);\r
c411b485 388 if ((RspTag != TPM_TAG_RSP_COMMAND) && (RspTag != TPM_TAG_RSP_AUTH1_COMMAND) && (RspTag != TPM_TAG_RSP_AUTH2_COMMAND)) {\r
e905fbb0 389 DEBUG ((DEBUG_ERROR, "TPM12: Response tag error - current tag value is %x\n", RspTag));\r
c1d93242
JY
390 Status = EFI_UNSUPPORTED;\r
391 goto Exit;\r
392 }\r
393\r
394 CopyMem (&Data32, (BufferOut + 2), sizeof (UINT32));\r
c411b485 395 TpmOutSize = SwapBytes32 (Data32);\r
c1d93242
JY
396 if (*SizeOut < TpmOutSize) {\r
397 Status = EFI_BUFFER_TOO_SMALL;\r
398 goto Exit;\r
399 }\r
c411b485 400\r
c1d93242
JY
401 *SizeOut = TpmOutSize;\r
402 //\r
403 // Continue reading the remaining data\r
404 //\r
405 while ( Index < TpmOutSize ) {\r
c411b485 406 for ( ; BurstCount > 0; BurstCount--) {\r
c1d93242
JY
407 *(BufferOut + Index) = MmioRead8 ((UINTN)&TisReg->DataFifo);\r
408 Index++;\r
409 if (Index == TpmOutSize) {\r
410 Status = EFI_SUCCESS;\r
411 goto Exit;\r
412 }\r
413 }\r
c411b485 414\r
c1d93242
JY
415 Status = Tpm12TisPcReadBurstCount (TisReg, &BurstCount);\r
416 if (EFI_ERROR (Status)) {\r
6f785cfc 417 Status = EFI_DEVICE_ERROR;\r
c1d93242
JY
418 goto Exit;\r
419 }\r
420 }\r
c411b485 421\r
c1d93242 422Exit:\r
f9f4fb23 423 DEBUG_CODE_BEGIN ();\r
c411b485
MK
424 DEBUG ((DEBUG_VERBOSE, "Tpm12TisTpmCommand Receive - "));\r
425 for (Index = 0; Index < TpmOutSize; Index++) {\r
426 DEBUG ((DEBUG_VERBOSE, "%02x ", BufferOut[Index]));\r
427 }\r
428\r
429 DEBUG ((DEBUG_VERBOSE, "\n"));\r
f9f4fb23 430 DEBUG_CODE_END ();\r
c411b485 431 MmioWrite8 ((UINTN)&TisReg->Status, TIS_PC_STS_READY);\r
c1d93242
JY
432 return Status;\r
433}\r
434\r
435/**\r
436 This service enables the sending of commands to the TPM12.\r
437\r
438 @param[in] InputParameterBlockSize Size of the TPM12 input parameter block.\r
439 @param[in] InputParameterBlock Pointer to the TPM12 input parameter block.\r
440 @param[in,out] OutputParameterBlockSize Size of the TPM12 output parameter block.\r
441 @param[in] OutputParameterBlock Pointer to the TPM12 output parameter block.\r
442\r
443 @retval EFI_SUCCESS The command byte stream was successfully sent to the device and a response was successfully received.\r
444 @retval EFI_DEVICE_ERROR The command was not successfully sent to the device or a response was not successfully received from the device.\r
b3548d32 445 @retval EFI_BUFFER_TOO_SMALL The output parameter block is too small.\r
c1d93242
JY
446**/\r
447EFI_STATUS\r
448EFIAPI\r
449Tpm12SubmitCommand (\r
c411b485
MK
450 IN UINT32 InputParameterBlockSize,\r
451 IN UINT8 *InputParameterBlock,\r
452 IN OUT UINT32 *OutputParameterBlockSize,\r
453 IN UINT8 *OutputParameterBlock\r
c1d93242
JY
454 )\r
455{\r
e4780913 456 PTP_INTERFACE_TYPE PtpInterface;\r
c1d93242 457\r
8e997ab8 458 //\r
e4780913 459 // Special handle for TPM1.2 to check PTP too, because PTP/TIS share same register address.\r
8e997ab8 460 //\r
c411b485 461 PtpInterface = Tpm12GetPtpInterface ((VOID *)(UINTN)PcdGet64 (PcdTpmBaseAddress));\r
e4780913 462 switch (PtpInterface) {\r
c411b485
MK
463 case PtpInterfaceFifo:\r
464 case PtpInterfaceTis:\r
465 return Tpm12TisTpmCommand (\r
466 (TIS_PC_REGISTERS_PTR)(UINTN)PcdGet64 (PcdTpmBaseAddress),\r
467 InputParameterBlock,\r
468 InputParameterBlockSize,\r
469 OutputParameterBlock,\r
470 OutputParameterBlockSize\r
471 );\r
472 case PtpInterfaceCrb:\r
e4780913
JY
473 //\r
474 // No need to support CRB because it is only accept TPM2 command.\r
475 //\r
c411b485
MK
476 default:\r
477 return EFI_DEVICE_ERROR;\r
8e997ab8 478 }\r
8e997ab8
JY
479}\r
480\r
481/**\r
482 Check whether the value of a TPM chip register satisfies the input BIT setting.\r
483\r
484 @param[in] Register Address port of register to be checked.\r
485 @param[in] BitSet Check these data bits are set.\r
486 @param[in] BitClear Check these data bits are clear.\r
487 @param[in] TimeOut The max wait time (unit MicroSecond) when checking register.\r
488\r
489 @retval EFI_SUCCESS The register satisfies the check bit.\r
490 @retval EFI_TIMEOUT The register can't run into the expected status in time.\r
491**/\r
492EFI_STATUS\r
493Tpm12PtpCrbWaitRegisterBits (\r
c411b485
MK
494 IN UINT32 *Register,\r
495 IN UINT32 BitSet,\r
496 IN UINT32 BitClear,\r
497 IN UINT32 TimeOut\r
8e997ab8
JY
498 )\r
499{\r
c411b485
MK
500 UINT32 RegRead;\r
501 UINT32 WaitTime;\r
8e997ab8 502\r
c411b485 503 for (WaitTime = 0; WaitTime < TimeOut; WaitTime += 30) {\r
8e997ab8 504 RegRead = MmioRead32 ((UINTN)Register);\r
c411b485 505 if (((RegRead & BitSet) == BitSet) && ((RegRead & BitClear) == 0)) {\r
8e997ab8
JY
506 return EFI_SUCCESS;\r
507 }\r
c411b485 508\r
8e997ab8
JY
509 MicroSecondDelay (30);\r
510 }\r
c411b485 511\r
8e997ab8
JY
512 return EFI_TIMEOUT;\r
513}\r
514\r
515/**\r
516 Get the control of TPM chip.\r
517\r
518 @param[in] CrbReg Pointer to CRB register.\r
519\r
520 @retval EFI_SUCCESS Get the control of TPM chip.\r
521 @retval EFI_INVALID_PARAMETER CrbReg is NULL.\r
522 @retval EFI_NOT_FOUND TPM chip doesn't exit.\r
523 @retval EFI_TIMEOUT Can't get the TPM control in time.\r
524**/\r
525EFI_STATUS\r
526Tpm12PtpCrbRequestUseTpm (\r
c411b485 527 IN PTP_CRB_REGISTERS_PTR CrbReg\r
8e997ab8
JY
528 )\r
529{\r
c411b485 530 EFI_STATUS Status;\r
8e997ab8 531\r
c411b485 532 MmioWrite32 ((UINTN)&CrbReg->LocalityControl, PTP_CRB_LOCALITY_CONTROL_REQUEST_ACCESS);\r
8e997ab8
JY
533 Status = Tpm12PtpCrbWaitRegisterBits (\r
534 &CrbReg->LocalityStatus,\r
535 PTP_CRB_LOCALITY_STATUS_GRANTED,\r
536 0,\r
537 PTP_TIMEOUT_A\r
538 );\r
539 return Status;\r
540}\r
541\r
c1d93242
JY
542/**\r
543 This service requests use TPM12.\r
544\r
545 @retval EFI_SUCCESS Get the control of TPM12 chip.\r
546 @retval EFI_NOT_FOUND TPM12 not found.\r
547 @retval EFI_DEVICE_ERROR Unexpected device behavior.\r
548**/\r
549EFI_STATUS\r
550EFIAPI\r
551Tpm12RequestUseTpm (\r
552 VOID\r
553 )\r
554{\r
8e997ab8
JY
555 PTP_INTERFACE_TYPE PtpInterface;\r
556\r
557 //\r
558 // Special handle for TPM1.2 to check PTP too, because PTP/TIS share same register address.\r
559 // Some other program might leverage this function to check the existence of TPM chip.\r
560 //\r
c411b485 561 PtpInterface = Tpm12GetPtpInterface ((VOID *)(UINTN)PcdGet64 (PcdTpmBaseAddress));\r
8e997ab8 562 switch (PtpInterface) {\r
c411b485
MK
563 case PtpInterfaceCrb:\r
564 return Tpm12PtpCrbRequestUseTpm ((PTP_CRB_REGISTERS_PTR)(UINTN)PcdGet64 (PcdTpmBaseAddress));\r
565 case PtpInterfaceFifo:\r
566 case PtpInterfaceTis:\r
567 return Tpm12TisPcRequestUseTpm ((TIS_PC_REGISTERS_PTR)(UINTN)PcdGet64 (PcdTpmBaseAddress));\r
568 default:\r
569 return EFI_NOT_FOUND;\r
8e997ab8 570 }\r
c1d93242 571}\r