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