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