TianoCore EDK2 master
Loading...
Searching...
No Matches
Tpm2Tis.c
Go to the documentation of this file.
1
11
12#include <Library/BaseLib.h>
14#include <Library/IoLib.h>
15#include <Library/TimerLib.h>
16#include <Library/DebugLib.h>
18#include <Library/PcdLib.h>
19
21
22#define TIS_TIMEOUT_MAX (90000 * 1000) // 90s
23
24//
25// Max TPM command/response length
26//
27#define TPMCMDBUFLENGTH 0x500
28
37BOOLEAN
40 )
41{
42 UINT8 RegRead;
43
44 RegRead = MmioRead8 ((UINTN)&TisReg->Access);
45 return (BOOLEAN)(RegRead != (UINT8)-1);
46}
47
61 IN UINT8 *Register,
62 IN UINT8 BitSet,
63 IN UINT8 BitClear,
64 IN UINT32 TimeOut
65 )
66{
67 UINT8 RegRead;
68 UINT32 WaitTime;
69
70 for (WaitTime = 0; WaitTime < TimeOut; WaitTime += 30) {
71 RegRead = MmioRead8 ((UINTN)Register);
72 if (((RegRead & BitSet) == BitSet) && ((RegRead & BitClear) == 0)) {
73 return EFI_SUCCESS;
74 }
75
77 }
78
79 return EFI_TIMEOUT;
80}
81
96 OUT UINT16 *BurstCount
97 )
98{
99 UINT32 WaitTime;
100 UINT8 DataByte0;
101 UINT8 DataByte1;
102
103 if ((BurstCount == NULL) || (TisReg == NULL)) {
104 return EFI_INVALID_PARAMETER;
105 }
106
107 WaitTime = 0;
108 do {
109 //
110 // TIS_PC_REGISTERS_PTR->burstCount is UINT16, but it is not 2bytes aligned,
111 // so it needs to use MmioRead8 to read two times
112 //
113 DataByte0 = MmioRead8 ((UINTN)&TisReg->BurstCount);
114 DataByte1 = MmioRead8 ((UINTN)&TisReg->BurstCount + 1);
115 *BurstCount = (UINT16)((DataByte1 << 8) + DataByte0);
116 if (*BurstCount != 0) {
117 return EFI_SUCCESS;
118 }
119
120 MicroSecondDelay (30);
121 WaitTime += 30;
122 } while (WaitTime < TIS_TIMEOUT_D);
123
124 return EFI_TIMEOUT;
125}
126
140 )
141{
142 EFI_STATUS Status;
143
144 if (TisReg == NULL) {
145 return EFI_INVALID_PARAMETER;
146 }
147
148 MmioWrite8 ((UINTN)&TisReg->Status, TIS_PC_STS_READY);
149 Status = TisPcWaitRegisterBits (
150 &TisReg->Status,
152 0,
153 TIS_TIMEOUT_B
154 );
155 return Status;
156}
157
172 )
173{
174 EFI_STATUS Status;
175
176 if (TisReg == NULL) {
177 return EFI_INVALID_PARAMETER;
178 }
179
180 if (!TisPcPresenceCheck (TisReg)) {
181 return EFI_NOT_FOUND;
182 }
183
184 MmioWrite8 ((UINTN)&TisReg->Access, TIS_PC_ACC_RQUUSE);
185 Status = TisPcWaitRegisterBits (
186 &TisReg->Access,
188 0,
189 TIS_TIMEOUT_A
190 );
191 return Status;
192}
193
212 IN UINT8 *BufferIn,
213 IN UINT32 SizeIn,
214 IN OUT UINT8 *BufferOut,
215 IN OUT UINT32 *SizeOut
216 )
217{
218 EFI_STATUS Status;
219 UINT16 BurstCount;
220 UINT32 Index;
221 UINT32 TpmOutSize;
222 UINT16 Data16;
223 UINT32 Data32;
224
226 UINTN DebugSize;
227
228 DEBUG ((DEBUG_VERBOSE, "Tpm2TisTpmCommand Send - "));
229 if (SizeIn > 0x100) {
230 DebugSize = 0x40;
231 } else {
232 DebugSize = SizeIn;
233 }
234
235 for (Index = 0; Index < DebugSize; Index++) {
236 DEBUG ((DEBUG_VERBOSE, "%02x ", BufferIn[Index]));
237 }
238
239 if (DebugSize != SizeIn) {
240 DEBUG ((DEBUG_VERBOSE, "...... "));
241 for (Index = SizeIn - 0x20; Index < SizeIn; Index++) {
242 DEBUG ((DEBUG_VERBOSE, "%02x ", BufferIn[Index]));
243 }
244 }
245
246 DEBUG ((DEBUG_VERBOSE, "\n"));
248 TpmOutSize = 0;
249
250 Status = TisPcPrepareCommand (TisReg);
251 if (EFI_ERROR (Status)) {
252 DEBUG ((DEBUG_ERROR, "Tpm2 is not ready for command!\n"));
253 return EFI_DEVICE_ERROR;
254 }
255
256 //
257 // Send the command data to Tpm
258 //
259 Index = 0;
260 while (Index < SizeIn) {
261 Status = TisPcReadBurstCount (TisReg, &BurstCount);
262 if (EFI_ERROR (Status)) {
263 Status = EFI_DEVICE_ERROR;
264 goto Exit;
265 }
266
267 for ( ; BurstCount > 0 && Index < SizeIn; BurstCount--) {
268 MmioWrite8 ((UINTN)&TisReg->DataFifo, *(BufferIn + Index));
269 Index++;
270 }
271 }
272
273 //
274 // Check the Tpm status STS_EXPECT change from 1 to 0
275 //
276 Status = TisPcWaitRegisterBits (
277 &TisReg->Status,
278 (UINT8)TIS_PC_VALID,
280 TIS_TIMEOUT_C
281 );
282 if (EFI_ERROR (Status)) {
283 DEBUG ((DEBUG_ERROR, "Tpm2 The send buffer too small!\n"));
284 Status = EFI_BUFFER_TOO_SMALL;
285 goto Exit;
286 }
287
288 //
289 // Executed the TPM command and waiting for the response data ready
290 //
291 MmioWrite8 ((UINTN)&TisReg->Status, TIS_PC_STS_GO);
292
293 //
294 // NOTE: That may take many seconds to minutes for certain commands, such as key generation.
295 //
296 Status = TisPcWaitRegisterBits (
297 &TisReg->Status,
298 (UINT8)(TIS_PC_VALID | TIS_PC_STS_DATA),
299 0,
300 TIS_TIMEOUT_MAX
301 );
302 if (EFI_ERROR (Status)) {
303 //
304 // dataAvail check timeout. Cancel the currently executing command by writing commandCancel,
305 // Expect TPM_RC_CANCELLED or successfully completed response.
306 //
307 DEBUG ((DEBUG_ERROR, "Wait for Tpm2 response data time out. Trying to cancel the command!!\n"));
308
309 MmioWrite32 ((UINTN)&TisReg->Status, TIS_PC_STS_CANCEL);
310 Status = TisPcWaitRegisterBits (
311 &TisReg->Status,
312 (UINT8)(TIS_PC_VALID | TIS_PC_STS_DATA),
313 0,
314 TIS_TIMEOUT_B
315 );
316 //
317 // Do not clear CANCEL bit here because Writes of 0 to this bit are ignored
318 //
319 if (EFI_ERROR (Status)) {
320 //
321 // Cancel executing command fail to get any response
322 // Try to abort the command with write of a 1 to commandReady in Command Execution state
323 //
324 Status = EFI_DEVICE_ERROR;
325 goto Exit;
326 }
327 }
328
329 //
330 // Get response data header
331 //
332 Index = 0;
333 BurstCount = 0;
334 while (Index < sizeof (TPM2_RESPONSE_HEADER)) {
335 Status = TisPcReadBurstCount (TisReg, &BurstCount);
336 if (EFI_ERROR (Status)) {
337 Status = EFI_DEVICE_ERROR;
338 goto Exit;
339 }
340
341 for ( ; BurstCount > 0; BurstCount--) {
342 *(BufferOut + Index) = MmioRead8 ((UINTN)&TisReg->DataFifo);
343 Index++;
344 if (Index == sizeof (TPM2_RESPONSE_HEADER)) {
345 break;
346 }
347 }
348 }
349
351 DEBUG ((DEBUG_VERBOSE, "Tpm2TisTpmCommand ReceiveHeader - "));
352 for (Index = 0; Index < sizeof (TPM2_RESPONSE_HEADER); Index++) {
353 DEBUG ((DEBUG_VERBOSE, "%02x ", BufferOut[Index]));
354 }
355
356 DEBUG ((DEBUG_VERBOSE, "\n"));
358 //
359 // Check the response data header (tag,parasize and returncode )
360 //
361 CopyMem (&Data16, BufferOut, sizeof (UINT16));
362 // TPM2 should not use this RSP_COMMAND
363 if (SwapBytes16 (Data16) == TPM_ST_RSP_COMMAND) {
364 DEBUG ((DEBUG_ERROR, "TPM2: TPM_ST_RSP error - %x\n", TPM_ST_RSP_COMMAND));
365 Status = EFI_UNSUPPORTED;
366 goto Exit;
367 }
368
369 CopyMem (&Data32, (BufferOut + 2), sizeof (UINT32));
370 TpmOutSize = SwapBytes32 (Data32);
371 if (*SizeOut < TpmOutSize) {
372 Status = EFI_BUFFER_TOO_SMALL;
373 goto Exit;
374 }
375
376 *SizeOut = TpmOutSize;
377 //
378 // Continue reading the remaining data
379 //
380 while ( Index < TpmOutSize ) {
381 for ( ; BurstCount > 0; BurstCount--) {
382 *(BufferOut + Index) = MmioRead8 ((UINTN)&TisReg->DataFifo);
383 Index++;
384 if (Index == TpmOutSize) {
385 Status = EFI_SUCCESS;
386 goto Exit;
387 }
388 }
389
390 Status = TisPcReadBurstCount (TisReg, &BurstCount);
391 if (EFI_ERROR (Status)) {
392 Status = EFI_DEVICE_ERROR;
393 goto Exit;
394 }
395 }
396
397Exit:
399 DEBUG ((DEBUG_VERBOSE, "Tpm2TisTpmCommand Receive - "));
400 for (Index = 0; Index < TpmOutSize; Index++) {
401 DEBUG ((DEBUG_VERBOSE, "%02x ", BufferOut[Index]));
402 }
403
404 DEBUG ((DEBUG_VERBOSE, "\n"));
406 MmioWrite8 ((UINTN)&TisReg->Status, TIS_PC_STS_READY);
407 return Status;
408}
409
423EFIAPI
425 IN UINT32 InputParameterBlockSize,
426 IN UINT8 *InputParameterBlock,
427 IN OUT UINT32 *OutputParameterBlockSize,
428 IN UINT8 *OutputParameterBlock
429 )
430{
431 return Tpm2TisTpmCommand (
432 (TIS_PC_REGISTERS_PTR)(UINTN)PcdGet64 (PcdTpmBaseAddress),
433 InputParameterBlock,
434 InputParameterBlockSize,
435 OutputParameterBlock,
436 OutputParameterBlockSize
437 );
438}
439
448EFIAPI
450 VOID
451 )
452{
453 return TisPcRequestUseTpm ((TIS_PC_REGISTERS_PTR)(UINTN)PcdGet64 (PcdTpmBaseAddress));
454}
UINT64 UINTN
UINTN EFIAPI MicroSecondDelay(IN UINTN MicroSeconds)
UINT16 EFIAPI SwapBytes16(IN UINT16 Value)
Definition: SwapBytes16.c:25
UINT32 EFIAPI SwapBytes32(IN UINT32 Value)
Definition: SwapBytes32.c:25
VOID *EFIAPI CopyMem(OUT VOID *DestinationBuffer, IN CONST VOID *SourceBuffer, IN UINTN Length)
UINT8 EFIAPI MmioRead8(IN UINTN Address)
Definition: IoLib.c:82
UINT8 EFIAPI MmioWrite8(IN UINTN Address, IN UINT8 Value)
Definition: IoLib.c:126
UINT32 EFIAPI MmioWrite32(IN UINTN Address, IN UINT32 Value)
Definition: IoLib.c:309
#define NULL
Definition: Base.h:319
#define IN
Definition: Base.h:279
#define OUT
Definition: Base.h:284
#define DEBUG_CODE_BEGIN()
Definition: DebugLib.h:564
#define DEBUG(Expression)
Definition: DebugLib.h:434
#define DEBUG_CODE_END()
Definition: DebugLib.h:578
#define PcdGet64(TokenName)
Definition: PcdLib.h:375
EFI_STATUS EFIAPI Register(IN EFI_PEI_RSC_HANDLER_CALLBACK Callback)
EFI_STATUS TisPcReadBurstCount(IN TIS_PC_REGISTERS_PTR TisReg, OUT UINT16 *BurstCount)
Definition: Tpm2Tis.c:94
EFI_STATUS EFIAPI DTpm2TisRequestUseTpm(VOID)
Definition: Tpm2Tis.c:449
BOOLEAN TisPcPresenceCheck(IN TIS_PC_REGISTERS_PTR TisReg)
Definition: Tpm2Tis.c:38
EFI_STATUS Tpm2TisTpmCommand(IN TIS_PC_REGISTERS_PTR TisReg, IN UINT8 *BufferIn, IN UINT32 SizeIn, IN OUT UINT8 *BufferOut, IN OUT UINT32 *SizeOut)
Definition: Tpm2Tis.c:210
EFI_STATUS TisPcRequestUseTpm(IN TIS_PC_REGISTERS_PTR TisReg)
Definition: Tpm2Tis.c:170
EFI_STATUS TisPcPrepareCommand(IN TIS_PC_REGISTERS_PTR TisReg)
Definition: Tpm2Tis.c:138
EFI_STATUS EFIAPI DTpm2TisSubmitCommand(IN UINT32 InputParameterBlockSize, IN UINT8 *InputParameterBlock, IN OUT UINT32 *OutputParameterBlockSize, IN UINT8 *OutputParameterBlock)
Definition: Tpm2Tis.c:424
EFI_STATUS TisPcWaitRegisterBits(IN UINT8 *Register, IN UINT8 BitSet, IN UINT8 BitClear, IN UINT32 TimeOut)
Definition: Tpm2Tis.c:60
#define TIS_PC_VALID
Definition: TpmTis.h:110
#define TIS_PC_ACC_ACTIVE
Definition: TpmTis.h:114
#define TIS_PC_ACC_RQUUSE
Definition: TpmTis.h:133
#define TIS_PC_STS_READY
Definition: TpmTis.h:151
#define TIS_PC_STS_GO
Definition: TpmTis.h:155
#define TIS_PC_STS_EXPECT
Definition: TpmTis.h:163
#define TIS_PC_STS_CANCEL
Definition: TpmTis.h:142
#define TIS_PC_STS_DATA
Definition: TpmTis.h:159
VOID EFIAPI Exit(IN EFI_STATUS Status)
RETURN_STATUS EFI_STATUS
Definition: UefiBaseType.h:29
#define EFI_SUCCESS
Definition: UefiBaseType.h:112