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