]> git.proxmox.com Git - mirror_edk2.git/blame - SecurityPkg/Tcg/TcgPei/TisPei.c
Handle TPM device error and avoid deadloop in BDS.
[mirror_edk2.git] / SecurityPkg / Tcg / TcgPei / TisPei.c
CommitLineData
0c18794e 1/** @file\r
2 TIS (TPM Interface Specification) functions used by TPM PEI driver.\r
3 \r
4Copyright (c) 2005 - 2011, Intel Corporation. All rights reserved.<BR>\r
5This program and the accompanying materials \r
6are licensed and made available under the terms and conditions of the BSD License \r
7which accompanies this distribution. The full text of the license may be found at \r
8http://opensource.org/licenses/bsd-license.php\r
9\r
10THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r
11WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
12\r
13**/\r
14\r
15#include <IndustryStandard/Tpm12.h>\r
16#include <IndustryStandard/UefiTcgPlatform.h>\r
17#include <Library/TpmCommLib.h>\r
18#include <Library/DebugLib.h>\r
19#include <Library/BaseLib.h>\r
20#include <Library/IoLib.h>\r
21#include <Library/BaseMemoryLib.h>\r
22\r
23/**\r
24 Send a command to TPM for execution and return response data.\r
25\r
26 @param[in] PeiServices Describes the list of possible PEI Services.\r
27 @param[in] TisReg TPM register space base address. \r
28 @param[in] BufferIn Buffer for command data. \r
29 @param[in] SizeIn Size of command data. \r
30 @param[in, out] BufferOut Buffer for response data. \r
31 @param[in, out] SizeOut Size of response data. \r
32 \r
33 @retval EFI_SUCCESS Operation completed successfully.\r
34 @retval EFI_TIMEOUT The register can't run into the expected status in time.\r
35 @retval EFI_BUFFER_TOO_SMALL Response data buffer is too small.\r
36 @retval EFI_DEVICE_ERROR Unexpected device behavior.\r
37\r
38**/\r
39EFI_STATUS\r
40TisTpmCommand (\r
41 IN EFI_PEI_SERVICES **PeiServices,\r
42 IN TIS_PC_REGISTERS_PTR TisReg,\r
43 IN UINT8 *BufferIn,\r
44 IN UINT32 SizeIn,\r
45 IN OUT UINT8 *BufferOut,\r
46 IN OUT UINT32 *SizeOut\r
47 )\r
48{\r
49 EFI_STATUS Status;\r
50 UINT16 BurstCount;\r
51 UINT32 Index;\r
52 UINT32 TpmOutSize;\r
53 UINT16 Data16;\r
54 UINT32 Data32;\r
55\r
56 Status = TisPcPrepareCommand (TisReg);\r
57 if (EFI_ERROR (Status)){\r
58 DEBUG ((DEBUG_ERROR, "Tpm is not ready for command!\n"));\r
59 return Status;\r
60 }\r
61 //\r
62 // Send the command data to Tpm\r
63 //\r
64 Index = 0;\r
65 while (Index < SizeIn) {\r
66 Status = TisPcReadBurstCount (TisReg, &BurstCount);\r
67 if (EFI_ERROR (Status)) {\r
68 Status = EFI_TIMEOUT;\r
69 goto Exit;\r
70 }\r
71 for (; BurstCount > 0 && Index < SizeIn; BurstCount--) {\r
72 MmioWrite8((UINTN)&TisReg->DataFifo, *(BufferIn + Index));\r
73 Index++;\r
74 }\r
75 }\r
76 //\r
77 // Check the Tpm status STS_EXPECT change from 1 to 0\r
78 //\r
79 Status = TisPcWaitRegisterBits (\r
80 &TisReg->Status,\r
81 (UINT8) TIS_PC_VALID,\r
82 TIS_PC_STS_EXPECT,\r
83 TIS_TIMEOUT_C\r
84 );\r
85 if (EFI_ERROR (Status)) {\r
86 DEBUG ((DEBUG_ERROR, "The send buffer too small!\n"));\r
87 Status = EFI_BUFFER_TOO_SMALL;\r
88 goto Exit;\r
89 }\r
90 //\r
91 // Executed the TPM command and waiting for the response data ready\r
92 //\r
93 MmioWrite8((UINTN)&TisReg->Status, TIS_PC_STS_GO);\r
94 Status = TisPcWaitRegisterBits (\r
95 &TisReg->Status,\r
96 (UINT8) (TIS_PC_VALID | TIS_PC_STS_DATA),\r
97 0,\r
98 TIS_TIMEOUT_B\r
99 );\r
100 if (EFI_ERROR (Status)) {\r
101 DEBUG ((DEBUG_ERROR, "Wait for Tpm response data time out!!\n"));\r
102 Status = EFI_TIMEOUT;\r
103 goto Exit;\r
104 }\r
105 //\r
106 // Get response data header\r
107 //\r
108 Index = 0;\r
109 BurstCount = 0;\r
110 while (Index < sizeof (TPM_RSP_COMMAND_HDR)) {\r
111 Status = TisPcReadBurstCount (TisReg, &BurstCount);\r
112 if (EFI_ERROR (Status)) {\r
113 Status = EFI_TIMEOUT;\r
114 goto Exit;\r
115 }\r
116 for (; BurstCount > 0; BurstCount--) {\r
117 *(BufferOut + Index) = MmioRead8 ((UINTN)&TisReg->DataFifo);\r
118 Index++;\r
119 if (Index == sizeof (TPM_RSP_COMMAND_HDR)) break;\r
120 }\r
121 }\r
122 //\r
123 // Check the reponse data header (tag,parasize and returncode )\r
124 //\r
125 CopyMem (&Data16, BufferOut, sizeof (UINT16));\r
126 if (SwapBytes16 (Data16) != TPM_TAG_RSP_COMMAND ) {\r
127 Status = EFI_DEVICE_ERROR;\r
128 goto Exit;\r
129 }\r
130 \r
131 CopyMem (&Data32, (BufferOut + 2), sizeof (UINT32));\r
132 TpmOutSize = SwapBytes32 (Data32);\r
133 if (*SizeOut < TpmOutSize) {\r
134 Status = EFI_BUFFER_TOO_SMALL;\r
135 goto Exit;\r
136 }\r
137 *SizeOut = TpmOutSize;\r
138 //\r
139 // Continue reading the remaining data\r
140 //\r
141 while ( Index < TpmOutSize ) {\r
142 for (; BurstCount > 0; BurstCount--) {\r
143 *(BufferOut + Index) = MmioRead8 ((UINTN)&TisReg->DataFifo);\r
144 Index++;\r
145 if (Index == TpmOutSize) {\r
146 Status = EFI_SUCCESS;\r
147 goto Exit;\r
148 }\r
149 }\r
150 Status = TisPcReadBurstCount (TisReg, &BurstCount);\r
151 if (EFI_ERROR (Status)) {\r
152 Status = EFI_TIMEOUT;\r
153 goto Exit;\r
154 }\r
155 }\r
156Exit:\r
157 MmioWrite8((UINTN)&TisReg->Status, TIS_PC_STS_READY);\r
158 return Status;\r
159}\r
160\r