]> git.proxmox.com Git - mirror_edk2.git/blame - SecurityPkg/Tcg/TcgDxe/TisDxe.c
SecurityPkg/TcgPei: Use updated Tpm12CommandLib APIs
[mirror_edk2.git] / SecurityPkg / Tcg / TcgDxe / TisDxe.c
CommitLineData
0c18794e 1/** @file \r
2 TIS (TPM Interface Specification) functions used by TPM Dxe driver.\r
3 \r
7cb1b15b 4Copyright (c) 2005 - 2016, Intel Corporation. All rights reserved.<BR>\r
0c18794e 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 <Library/TimerLib.h>\r
7cb1b15b 17#include <Library/Tpm12DeviceLib.h>\r
0c18794e 18#include <Library/DebugLib.h>\r
0c18794e 19#include <Library/BaseLib.h>\r
20#include <Library/BaseMemoryLib.h>\r
21\r
7cb1b15b
MK
22//\r
23// Max TPM command/reponse length\r
24//\r
25#define TPMCMDBUFLENGTH SIZE_1KB\r
0c18794e 26\r
7cb1b15b
MK
27STATIC UINT8 TpmCommandBuf[TPMCMDBUFLENGTH];\r
28STATIC UINT8 TpmResponseBuf[TPMCMDBUFLENGTH];\r
0c18794e 29\r
30/**\r
31 Format TPM command data according to the format control character.\r
32\r
33 @param[in] FmtChar Format control character. \r
34 @param[in, out] ap List of arguments. \r
35 @param[in] TpmBuffer Buffer for TPM command data. \r
36 @param[out] DataLength TPM command data length. \r
37 \r
38 @retval EFI_SUCCESS Operation completed successfully.\r
39 @retval EFI_INVALID_PARAMETER Invalid format control character.\r
40 @retval EFI_BUFFER_TOO_SMALL Buffer too small for command data.\r
41\r
42**/\r
43EFI_STATUS\r
44TisPcSendV (\r
45 IN UINT8 FmtChar,\r
46 IN OUT VA_LIST *ap,\r
47 UINT8 *TpmBuffer,\r
48 UINT32 *DataLength\r
49 )\r
50{\r
51 UINT8 DataByte;\r
52 UINT16 DataWord;\r
53 UINT32 DataDword;\r
54 TPM_RQU_COMMAND_HDR TpmCmdHdr;\r
55 TPM_RQU_COMMAND_HDR *TpmCmdPtr;\r
56 UINTN Size;\r
57 UINT8 *Raw;\r
58\r
59 switch (FmtChar) {\r
60\r
61 case 'b':\r
62 DataByte = VA_ARG (*ap, UINT8);\r
63 Raw = &DataByte;\r
64 Size = sizeof (DataByte);\r
65 break;\r
66\r
67 case 'w':\r
68 DataWord = VA_ARG (*ap, UINT16);\r
69 DataWord = SwapBytes16 (DataWord);\r
70 Raw = (UINT8*)&DataWord;\r
71 Size = sizeof (DataWord);\r
72 break;\r
73\r
74 case 'd':\r
75 DataDword = VA_ARG (*ap, UINT32);\r
76 DataDword = SwapBytes32 (DataDword);\r
77 Raw = (UINT8*)&DataDword;\r
78 Size = sizeof (DataDword);\r
79 break;\r
80\r
81 case 'h':\r
82 TpmCmdPtr = VA_ARG (*ap, TPM_RQU_COMMAND_HDR*);\r
83 TpmCmdHdr.tag = SwapBytes16 (TpmCmdPtr->tag);\r
84 TpmCmdHdr.paramSize = SwapBytes32 (TpmCmdPtr->paramSize);\r
85 TpmCmdHdr.ordinal = SwapBytes32 (TpmCmdPtr->ordinal);\r
86 Raw = (UINT8*) &TpmCmdHdr;\r
87 Size = sizeof (TpmCmdHdr);\r
88 break;\r
89\r
90 case 'r':\r
91 Raw = VA_ARG (*ap, UINT8*);\r
92 Size = VA_ARG (*ap, UINTN);\r
93 break;\r
94\r
95 case '\0':\r
96 return EFI_INVALID_PARAMETER;\r
97\r
98 default:\r
99 return EFI_INVALID_PARAMETER;\r
100 }\r
101\r
be02dcee 102 //\r
103 // Check input to avoid overflow.\r
104 //\r
105 if ((UINT32) (~0)- *DataLength < (UINT32)Size) {\r
106 return EFI_INVALID_PARAMETER;\r
107 }\r
108\r
0c18794e 109 if(*DataLength + (UINT32) Size > TPMCMDBUFLENGTH) {\r
110 return EFI_BUFFER_TOO_SMALL;\r
111 }\r
112 CopyMem (TpmBuffer + *DataLength, Raw, Size);\r
113 *DataLength += (UINT32) Size;\r
114 return EFI_SUCCESS;\r
115}\r
116\r
117/**\r
118 Format reponse data according to the format control character.\r
119\r
120 @param[in] FmtChar Format control character. \r
121 @param[in, out] ap List of arguments. \r
122 @param[out] TpmBuffer Buffer for reponse data. \r
123 @param[in, out] DataIndex Data offset in reponse data buffer. \r
124 @param[in] RespSize Response data length. \r
125 @param[out] DataFinished Reach the end of Response data. \r
126 \r
127 @retval EFI_SUCCESS Operation completed successfully.\r
128 @retval EFI_INVALID_PARAMETER Invalid format control character.\r
129 @retval EFI_BUFFER_TOO_SMALL Buffer too small for command data.\r
130\r
131**/\r
132EFI_STATUS\r
133TisPcReceiveV (\r
134 IN UINT8 FmtChar,\r
135 IN OUT VA_LIST *ap,\r
136 OUT UINT8 *TpmBuffer,\r
137 IN OUT UINT32 *DataIndex,\r
138 IN UINT32 RespSize,\r
139 OUT BOOLEAN *DataFinished\r
140 )\r
141{\r
142 UINT8 *Raw;\r
143 TPM_RSP_COMMAND_HDR *TpmRspPtr;\r
144 UINTN Size;\r
145\r
146 Raw = VA_ARG (*ap, UINT8*);\r
147 switch (FmtChar) {\r
148\r
149 case 'b':\r
150 Size = sizeof (UINT8);\r
151 break;\r
152\r
153 case 'w':\r
154 Size = sizeof (UINT16);\r
155 break;\r
156\r
157 case 'd':\r
158 Size = sizeof (UINT32);\r
159 break;\r
160\r
161 case 'h':\r
162 Size = sizeof (*TpmRspPtr);\r
163 break;\r
164\r
165 case 'r':\r
166 Size = VA_ARG (*ap, UINTN);\r
be02dcee 167 //\r
168 // If overflowed, which means Size is big enough for Response data. \r
169 // skip this check. Copy the whole data \r
170 //\r
171 if ((UINT32) (~0)- *DataIndex >= (UINT32)Size) {\r
172 if(*DataIndex + (UINT32) Size <= RespSize) {\r
173 break;\r
174 }\r
0c18794e 175 }\r
be02dcee 176\r
0c18794e 177 *DataFinished = TRUE;\r
178 if (*DataIndex >= RespSize) {\r
179 return EFI_SUCCESS;\r
180 }\r
181 CopyMem (Raw, TpmBuffer + *DataIndex, RespSize - *DataIndex);\r
182 *DataIndex += RespSize - *DataIndex;\r
183 return EFI_SUCCESS;\r
184\r
185 case '\0':\r
186 return EFI_INVALID_PARAMETER;\r
187\r
188 default:\r
189 return EFI_WARN_UNKNOWN_GLYPH;\r
190 }\r
191\r
192 if(*DataIndex + (UINT32) Size > RespSize) {\r
193 *DataFinished = TRUE;\r
194 return EFI_SUCCESS;\r
195 }\r
196\r
197 if( *DataIndex + (UINT32) Size > TPMCMDBUFLENGTH )\r
198 return EFI_BUFFER_TOO_SMALL;\r
199\r
200 CopyMem (Raw, TpmBuffer + *DataIndex, Size);\r
201 *DataIndex += (UINT32) Size;\r
202\r
203 switch (FmtChar) {\r
204\r
205 case 'w':\r
206 *(UINT16*)Raw = SwapBytes16 (*(UINT16*) Raw);\r
207 break;\r
208\r
209 case 'd':\r
210 *(UINT32*)Raw = SwapBytes32 (*(UINT32*) Raw);\r
211 break;\r
212\r
213 case 'h':\r
214 TpmRspPtr = (TPM_RSP_COMMAND_HDR*) Raw;\r
215 TpmRspPtr->tag = SwapBytes16 (TpmRspPtr->tag);\r
216 TpmRspPtr->paramSize = SwapBytes32 (TpmRspPtr->paramSize);\r
217 TpmRspPtr->returnCode = SwapBytes32 (TpmRspPtr->returnCode);\r
218 break;\r
219 }\r
220 return EFI_SUCCESS;\r
221}\r
222\r
223/**\r
224 Send formatted command to TPM for execution and return formatted data from response.\r
225\r
226 @param[in] TisReg TPM Handle. \r
227 @param[in] Fmt Format control string. \r
228 @param[in] ... The variable argument list.\r
229 \r
230 @retval EFI_SUCCESS Operation completed successfully.\r
231 @retval EFI_TIMEOUT The register can't run into the expected status in time.\r
232\r
233**/\r
234EFI_STATUS\r
235EFIAPI\r
236TisPcExecute (\r
0c18794e 237 IN CONST CHAR8 *Fmt,\r
238 ...\r
239 )\r
240{\r
241 EFI_STATUS Status;\r
242 VA_LIST Ap;\r
243 UINT32 BufSize;\r
244 UINT32 ResponseSize;\r
245 BOOLEAN DataFinished;\r
246\r
247 VA_START (Ap, Fmt);\r
248\r
249 //\r
250 // Put the formatted command to the TpmCommandBuf\r
251 //\r
252 BufSize = 0;\r
253 while (*Fmt != '\0') {\r
254 if (*Fmt == '%') Fmt++;\r
255 if (*Fmt == '/') break;\r
256 Status = TisPcSendV (*Fmt, &Ap, TpmCommandBuf, &BufSize);\r
257 if (EFI_ERROR( Status )) {\r
3bbe68a3 258 goto Error;\r
0c18794e 259 }\r
260 Fmt++;\r
261 }\r
0c18794e 262\r
0c18794e 263 //\r
7cb1b15b 264 // Send the command to TPM\r
0c18794e 265 //\r
7cb1b15b
MK
266 ZeroMem (TpmResponseBuf, sizeof (TpmResponseBuf));\r
267 ResponseSize = sizeof (TpmResponseBuf);\r
268 Status = Tpm12SubmitCommand (BufSize, TpmCommandBuf, &ResponseSize, TpmResponseBuf);\r
0c18794e 269 if (EFI_ERROR (Status)) {\r
3bbe68a3 270 goto Error;\r
0c18794e 271 }\r
7cb1b15b
MK
272 Fmt++;\r
273\r
0c18794e 274 //\r
7cb1b15b 275 // Get the formatted data from the TpmResponseBuf.\r
0c18794e 276 //\r
277 BufSize =0;\r
278 DataFinished = FALSE;\r
279 while (*Fmt != '\0') {\r
280 if (*Fmt == '%') {\r
281 Fmt++;\r
282 }\r
7cb1b15b 283 Status = TisPcReceiveV (*Fmt, &Ap, TpmResponseBuf, &BufSize, ResponseSize, &DataFinished);\r
0c18794e 284 if (EFI_ERROR (Status)) {\r
3bbe68a3 285 goto Error;\r
0c18794e 286 }\r
287 if (DataFinished) {\r
3bbe68a3 288 VA_END (Ap);\r
0c18794e 289 return EFI_SUCCESS;\r
290 }\r
291 Fmt++;\r
292 }\r
293\r
3bbe68a3 294Error:\r
0c18794e 295 VA_END (Ap);\r
296 return Status;\r
297}\r
298\r