1 /** @file 2 Basic TIS (TPM Interface Specification) functions for Infineon I2C TPM. 3 4 Copyright (c) 2013 - 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 <PiPei.h> 16 #include <Library/Tpm12DeviceLib.h> 17 #include <Library/BaseLib.h> 18 #include <Library/TimerLib.h> 19 #include <Library/DebugLib.h> 20 #include <Library/I2cLib.h> 21 22 // 23 // Default TPM (Infineon SLB9645) I2C Slave Device Address on Crosshill board. 24 // 25 #define TPM_I2C_SLAVE_DEVICE_ADDRESS 0x20 26 27 // 28 // Default Infineon SLB9645 TPM I2C mapped registers (SLB9645 I2C Comm. Protocol Application Note). 29 // 30 #define INFINEON_TPM_ACCESS_0_ADDRESS_DEFAULT 0x0 31 #define INFINEON_TPM_STS_0_ADDRESS_DEFAULT 0x01 32 #define INFINEON_TPM_BURST0_COUNT_0_DEFAULT 0x02 33 #define INFINEON_TPM_BURST1_COUNT_0_DEFAULT 0x03 34 #define INFINEON_TPM_DATA_FIFO_0_ADDRESS_DEFAULT 0x05 35 #define INFINEON_TPM_DID_VID_0_DEFAULT 0x09 36 37 // 38 // Max. retry count for read transfers (as recommended by Infineon). 39 // 40 #define READ_RETRY 3 41 42 // 43 // Guard time of 250us between I2C read and next I2C write transfer (as recommended by Infineon). 44 // 45 #define GUARD_TIME 250 46 47 // 48 // Define bits of ACCESS and STATUS registers 49 // 50 51 /// 52 /// This bit is a 1 to indicate that the other bits in this register are valid. 53 /// 54 #define TIS_PC_VALID BIT7 55 /// 56 /// Indicate that this locality is active. 57 /// 58 #define TIS_PC_ACC_ACTIVE BIT5 59 /// 60 /// Set to 1 to indicate that this locality had the TPM taken away while 61 /// this locality had the TIS_PC_ACC_ACTIVE bit set. 62 /// 63 #define TIS_PC_ACC_SEIZED BIT4 64 /// 65 /// Set to 1 to indicate that TPM MUST reset the 66 /// TIS_PC_ACC_ACTIVE bit and remove ownership for localities less than the 67 /// locality that is writing this bit. 68 /// 69 #define TIS_PC_ACC_SEIZE BIT3 70 /// 71 /// When this bit is 1, another locality is requesting usage of the TPM. 72 /// 73 #define TIS_PC_ACC_PENDIND BIT2 74 /// 75 /// Set to 1 to indicate that this locality is requesting to use TPM. 76 /// 77 #define TIS_PC_ACC_RQUUSE BIT1 78 /// 79 /// A value of 1 indicates that a T/OS has not been established on the platform 80 /// 81 #define TIS_PC_ACC_ESTABLISH BIT0 82 83 /// 84 /// When this bit is 1, TPM is in the Ready state, 85 /// indicating it is ready to receive a new command. 86 /// 87 #define TIS_PC_STS_READY BIT6 88 /// 89 /// Write a 1 to this bit to cause the TPM to execute that command. 90 /// 91 #define TIS_PC_STS_GO BIT5 92 /// 93 /// This bit indicates that the TPM has data available as a response. 94 /// 95 #define TIS_PC_STS_DATA BIT4 96 /// 97 /// The TPM sets this bit to a value of 1 when it expects another byte of data for a command. 98 /// 99 #define TIS_PC_STS_EXPECT BIT3 100 /// 101 /// Writes a 1 to this bit to force the TPM to re-send the response. 102 /// 103 #define TIS_PC_STS_RETRY BIT1 104 105 // 106 // Default TimeOut values in microseconds 107 // 108 #define TIS_TIMEOUT_A (750 * 1000) // 750ms 109 #define TIS_TIMEOUT_B (2000 * 1000) // 2s 110 #define TIS_TIMEOUT_C (750 * 1000) // 750ms 111 #define TIS_TIMEOUT_D (750 * 1000) // 750ms 112 113 // 114 // Global variable to indicate if TPM I2C Read Transfer has previously occurred. 115 // NOTE: Given the GUARD_TIME requirement (TpmAccess.h), if this library loaded 116 // by PEI Drivers this global variable required to be resident in R/W memory 117 // 118 BOOLEAN mI2CPrevReadTransfer = FALSE; 119 120 /** 121 Writes single byte data to TPM specified by I2C register address. 122 123 @param[in] TpmAddress The register to write. 124 @param[in] Data The data to write to the register. 125 126 **/ 127 VOID 128 TpmWriteByte ( 129 IN UINTN TpmAddress, 130 IN UINT8 Data 131 ) 132 { 133 EFI_STATUS Status; 134 UINTN WriteLength; 135 UINT8 WriteData[2]; 136 EFI_I2C_DEVICE_ADDRESS I2CDeviceAddr; 137 138 // 139 // Setup I2C Slave device address and address mode (7-bit). 140 // 141 I2CDeviceAddr.I2CDeviceAddress = TPM_I2C_SLAVE_DEVICE_ADDRESS; 142 143 // 144 // As recommended by Infineon (SLB9645 I2C Communication protocol application 145 // note revision 1.0) wait 250 microseconds between a read and a write transfer. 146 // 147 if (mI2CPrevReadTransfer) { 148 MicroSecondDelay (GUARD_TIME); 149 } 150 151 // 152 // Write to TPM register. 153 // 154 WriteLength = 2; 155 WriteData[0] = (UINT8)TpmAddress; 156 WriteData[1] = Data; 157 158 Status = I2cWriteMultipleByte ( 159 I2CDeviceAddr, 160 EfiI2CSevenBitAddrMode, 161 &WriteLength, 162 &WriteData 163 ); 164 if (EFI_ERROR(Status)) { 165 DEBUG ((EFI_D_ERROR, "TpmWriteByte(): I2C Write to TPM address %0x failed (%r)\n", TpmAddress, Status)); 166 ASSERT (FALSE); // Writes to TPM should always succeed. 167 } 168 169 mI2CPrevReadTransfer = FALSE; 170 } 171 172 /** 173 Reads single byte data from TPM specified by I2C register address. 174 175 Due to stability issues when using I2C combined write/read transfers (with 176 RESTART) to TPM (specifically read from status register), a single write is 177 performed followed by single read (with STOP condition in between). 178 179 @param[in] TpmAddress Address of register to read. 180 181 @return The value register read. 182 183 **/ 184 UINT8 185 TpmReadByte ( 186 IN UINTN TpmAddress 187 ) 188 { 189 UINT8 Data[1]; 190 UINT8 ReadData; 191 UINT8 ReadCount; 192 193 EFI_I2C_DEVICE_ADDRESS I2CDeviceAddr; 194 EFI_I2C_ADDR_MODE I2CAddrMode; 195 196 EFI_STATUS Status; 197 198 Status = EFI_SUCCESS; 199 ReadData = 0xFF; 200 ReadCount = 0; 201 202 // 203 // Locate I2C protocol for TPM I2C access. 204 // 205 I2CDeviceAddr.I2CDeviceAddress = TPM_I2C_SLAVE_DEVICE_ADDRESS; 206 I2CAddrMode = EfiI2CSevenBitAddrMode; 207 208 // 209 // As recommended by Infineon (SLB9645 I2C Communication protocol application 210 // note revision 1.0) retry up to 3 times if TPM status, access or burst count 211 // registers return 0xFF. 212 // 213 while ((ReadData == 0xFF) && (ReadCount < READ_RETRY)) { 214 // 215 // As recommended by Infineon (SLB9645 I2C Communication protocol application 216 // note revision 1.0) wait 250 microseconds between a read and a write transfer. 217 // 218 if (mI2CPrevReadTransfer) { 219 MicroSecondDelay (GUARD_TIME); 220 } 221 222 // 223 // Write address to TPM. 224 // 225 Data[0] = (UINT8)TpmAddress; 226 Status = I2cWriteByte ( 227 I2CDeviceAddr, 228 I2CAddrMode, 229 &Data 230 ); 231 232 if (EFI_ERROR(Status)) { 233 DEBUG ((EFI_D_INFO, "TpmReadByte(): write to TPM address %0x failed (%r)\n", TpmAddress, Status)); 234 } 235 236 mI2CPrevReadTransfer = FALSE; 237 238 // 239 // Read data from TPM. 240 // 241 Data[0] = (UINT8)TpmAddress; 242 Status = I2cReadByte ( 243 I2CDeviceAddr, 244 I2CAddrMode, 245 &Data 246 ); 247 248 if (EFI_ERROR(Status)) { 249 DEBUG ((EFI_D_INFO, "TpmReadByte(): read from TPM address %0x failed (%r)\n", TpmAddress, Status)); 250 ReadData = 0xFF; 251 } else { 252 ReadData = Data[0]; 253 } 254 255 // 256 // Only need to retry 3 times for TPM status, access, and burst count registers. 257 // If read transfer is to TPM Data FIFO, do not retry, exit loop. 258 // 259 if (TpmAddress == INFINEON_TPM_DATA_FIFO_0_ADDRESS_DEFAULT) { 260 ReadCount = READ_RETRY; 261 } else { 262 ReadCount++; 263 } 264 265 mI2CPrevReadTransfer = TRUE; 266 } 267 268 if (EFI_ERROR(Status)) { 269 // 270 // Only reads to access register allowed to fail. 271 // 272 if (TpmAddress != INFINEON_TPM_ACCESS_0_ADDRESS_DEFAULT) { 273 DEBUG ((EFI_D_ERROR, "TpmReadByte(): read from TPM address %0x failed\n", TpmAddress)); 274 ASSERT_EFI_ERROR (Status); 275 } 276 } 277 return ReadData; 278 } 279 280 /** 281 Check whether the value of a TPM chip register satisfies the input BIT setting. 282 283 @param[in] Register TPM register to be checked. 284 @param[in] BitSet Check these data bits are set. 285 @param[in] BitClear Check these data bits are clear. 286 @param[in] TimeOut The max wait time (unit MicroSecond) when checking register. 287 288 @retval EFI_SUCCESS The register satisfies the check bit. 289 @retval EFI_TIMEOUT The register can't run into the expected status in time. 290 **/ 291 EFI_STATUS 292 TisPcWaitRegisterBits ( 293 IN UINTN Register, 294 IN UINT8 BitSet, 295 IN UINT8 BitClear, 296 IN UINT32 TimeOut 297 ) 298 { 299 UINT8 RegRead; 300 UINT32 WaitTime; 301 302 for (WaitTime = 0; WaitTime < TimeOut; WaitTime += 30){ 303 RegRead = TpmReadByte (Register); 304 if ((RegRead & BitSet) == BitSet && (RegRead & BitClear) == 0) 305 return EFI_SUCCESS; 306 MicroSecondDelay (30); 307 } 308 return EFI_TIMEOUT; 309 } 310 311 /** 312 Get BurstCount by reading the burstCount field of a TIS register 313 in the time of default TIS_TIMEOUT_D. 314 315 @param[out] BurstCount Pointer to a buffer to store the got BurstConut. 316 317 @retval EFI_SUCCESS Get BurstCount. 318 @retval EFI_INVALID_PARAMETER BurstCount is NULL. 319 @retval EFI_TIMEOUT BurstCount can't be got in time. 320 **/ 321 EFI_STATUS 322 TisPcReadBurstCount ( 323 OUT UINT16 *BurstCount 324 ) 325 { 326 UINT32 WaitTime; 327 UINT8 DataByte0; 328 UINT8 DataByte1; 329 330 if (BurstCount == NULL) { 331 return EFI_INVALID_PARAMETER; 332 } 333 334 WaitTime = 0; 335 do { 336 // 337 // BurstCount is UINT16, but it is not 2bytes aligned, 338 // so it needs to use TpmReadByte to read two times 339 // 340 DataByte0 = TpmReadByte (INFINEON_TPM_BURST0_COUNT_0_DEFAULT); 341 DataByte1 = TpmReadByte (INFINEON_TPM_BURST1_COUNT_0_DEFAULT); 342 *BurstCount = (UINT16)((DataByte1 << 8) + DataByte0); 343 if (*BurstCount != 0) { 344 return EFI_SUCCESS; 345 } 346 MicroSecondDelay (30); 347 WaitTime += 30; 348 } while (WaitTime < TIS_TIMEOUT_D); 349 350 return EFI_TIMEOUT; 351 } 352 353 /** 354 Set TPM chip to ready state by sending ready command TIS_PC_STS_READY 355 to Status Register in time. 356 357 @retval EFI_SUCCESS TPM chip enters into ready state. 358 @retval EFI_TIMEOUT TPM chip can't be set to ready state in time. 359 **/ 360 EFI_STATUS 361 TisPcPrepareCommand ( 362 VOID 363 ) 364 { 365 EFI_STATUS Status; 366 367 TpmWriteByte (INFINEON_TPM_STS_0_ADDRESS_DEFAULT, TIS_PC_STS_READY); 368 Status = TisPcWaitRegisterBits ( 369 INFINEON_TPM_STS_0_ADDRESS_DEFAULT, 370 TIS_PC_STS_READY, 371 0, 372 TIS_TIMEOUT_B 373 ); 374 return Status; 375 } 376 377 /** 378 This service requests use TPM12. 379 380 @retval EFI_SUCCESS Get the control of TPM12 chip. 381 @retval EFI_NOT_FOUND TPM12 not found. 382 @retval EFI_DEVICE_ERROR Unexpected device behavior. 383 **/ 384 EFI_STATUS 385 EFIAPI 386 Tpm12RequestUseTpm ( 387 VOID 388 ) 389 { 390 EFI_STATUS Status; 391 392 // 393 // Check to see if TPM exists 394 // 395 if (TpmReadByte (INFINEON_TPM_ACCESS_0_ADDRESS_DEFAULT) == 0xFF) { 396 return EFI_NOT_FOUND; 397 } 398 399 TpmWriteByte (INFINEON_TPM_ACCESS_0_ADDRESS_DEFAULT, TIS_PC_ACC_RQUUSE); 400 401 // 402 // No locality set before, ACCESS_X.activeLocality MUST be valid within TIMEOUT_A 403 // 404 Status = TisPcWaitRegisterBits ( 405 INFINEON_TPM_ACCESS_0_ADDRESS_DEFAULT, 406 (UINT8)(TIS_PC_ACC_ACTIVE |TIS_PC_VALID), 407 0, 408 TIS_TIMEOUT_A 409 ); 410 return Status; 411 } 412 413 /** 414 Send command to TPM for execution. 415 416 @param[in] TpmBuffer Buffer for TPM command data. 417 @param[in] DataLength TPM command data length. 418 419 @retval EFI_SUCCESS Operation completed successfully. 420 @retval EFI_TIMEOUT The register can't run into the expected status in time. 421 422 **/ 423 EFI_STATUS 424 TisPcSend ( 425 IN UINT8 *TpmBuffer, 426 IN UINT32 DataLength 427 ) 428 { 429 UINT16 BurstCount; 430 UINT32 Index; 431 EFI_STATUS Status; 432 433 Status = TisPcPrepareCommand (); 434 if (EFI_ERROR (Status)){ 435 DEBUG ((DEBUG_ERROR, "The TPM is not ready!\n")); 436 goto Done; 437 } 438 Index = 0; 439 while (Index < DataLength) { 440 Status = TisPcReadBurstCount (&BurstCount); 441 if (EFI_ERROR (Status)) { 442 Status = EFI_TIMEOUT; 443 goto Done; 444 } 445 for (; BurstCount > 0 && Index < DataLength; BurstCount--) { 446 TpmWriteByte (INFINEON_TPM_DATA_FIFO_0_ADDRESS_DEFAULT, *(TpmBuffer + Index)); 447 Index++; 448 } 449 } 450 // 451 // Ensure the TPM status STS_EXPECT change from 1 to 0 452 // 453 Status = TisPcWaitRegisterBits ( 454 INFINEON_TPM_STS_0_ADDRESS_DEFAULT, 455 (UINT8) TIS_PC_VALID, 456 TIS_PC_STS_EXPECT, 457 TIS_TIMEOUT_C 458 ); 459 if (EFI_ERROR (Status)) { 460 goto Done; 461 } 462 463 // 464 // Start the command 465 // 466 TpmWriteByte (INFINEON_TPM_STS_0_ADDRESS_DEFAULT, TIS_PC_STS_GO); 467 468 Done: 469 if (EFI_ERROR (Status)) { 470 // 471 // Ensure the TPM state change from "Reception" to "Idle/Ready" 472 // 473 TpmWriteByte (INFINEON_TPM_STS_0_ADDRESS_DEFAULT, TIS_PC_STS_READY); 474 } 475 476 return Status; 477 } 478 479 /** 480 Receive response data of last command from TPM. 481 482 @param[out] TpmBuffer Buffer for response data. 483 @param[out] RespSize Response data length. 484 485 @retval EFI_SUCCESS Operation completed successfully. 486 @retval EFI_TIMEOUT The register can't run into the expected status in time. 487 @retval EFI_DEVICE_ERROR Unexpected device status. 488 @retval EFI_BUFFER_TOO_SMALL Response data is too long. 489 490 **/ 491 EFI_STATUS 492 TisPcReceive ( 493 OUT UINT8 *TpmBuffer, 494 OUT UINT32 *RespSize 495 ) 496 { 497 EFI_STATUS Status; 498 UINT16 BurstCount; 499 UINT32 Index; 500 UINT32 ResponseSize; 501 TPM_RSP_COMMAND_HDR *ResponseHeader; 502 503 // 504 // Wait for the command completion 505 // 506 Status = TisPcWaitRegisterBits ( 507 INFINEON_TPM_STS_0_ADDRESS_DEFAULT, 508 (UINT8) (TIS_PC_VALID | TIS_PC_STS_DATA), 509 0, 510 TIS_TIMEOUT_B 511 ); 512 if (EFI_ERROR (Status)) { 513 Status = EFI_TIMEOUT; 514 goto Done; 515 } 516 // 517 // Read the response data header and check it 518 // 519 Index = 0; 520 BurstCount = 0; 521 while (Index < sizeof (TPM_RSP_COMMAND_HDR)) { 522 Status = TisPcReadBurstCount (&BurstCount); 523 if (EFI_ERROR (Status)) { 524 Status = EFI_TIMEOUT; 525 goto Done; 526 } 527 for (; BurstCount > 0 ; BurstCount--) { 528 *(TpmBuffer + Index) = TpmReadByte (INFINEON_TPM_DATA_FIFO_0_ADDRESS_DEFAULT); 529 Index++; 530 if (Index == sizeof (TPM_RSP_COMMAND_HDR)) 531 break; 532 } 533 } 534 535 // 536 // Check the response data header (tag, parasize and returncode) 537 // 538 ResponseHeader = (TPM_RSP_COMMAND_HDR *)TpmBuffer; 539 if (SwapBytes16 (ReadUnaligned16 (&ResponseHeader->tag)) != TPM_TAG_RSP_COMMAND) { 540 Status = EFI_DEVICE_ERROR; 541 goto Done; 542 } 543 544 ResponseSize = SwapBytes32 (ReadUnaligned32 (&ResponseHeader->paramSize)); 545 if (ResponseSize == sizeof (TPM_RSP_COMMAND_HDR)) { 546 Status = EFI_SUCCESS; 547 goto Done; 548 } 549 if (ResponseSize < sizeof (TPM_RSP_COMMAND_HDR)) { 550 Status = EFI_DEVICE_ERROR; 551 goto Done; 552 } 553 if (*RespSize < ResponseSize) { 554 Status = EFI_BUFFER_TOO_SMALL; 555 goto Done; 556 } 557 *RespSize = ResponseSize; 558 559 // 560 // Continue reading the remaining data 561 // 562 while (Index < ResponseSize) { 563 for (; BurstCount > 0 ; BurstCount--) { 564 *(TpmBuffer + Index) = TpmReadByte (INFINEON_TPM_DATA_FIFO_0_ADDRESS_DEFAULT); 565 Index++; 566 if (Index == ResponseSize) { 567 Status = EFI_SUCCESS; 568 goto Done; 569 } 570 } 571 Status = TisPcReadBurstCount (&BurstCount); 572 if (EFI_ERROR (Status) && (Index < ResponseSize)) { 573 Status = EFI_DEVICE_ERROR; 574 goto Done; 575 } 576 } 577 578 Done: 579 // 580 // Ensure the TPM state change from "Execution" or "Completion" to "Idle/Ready" 581 // 582 TpmWriteByte (INFINEON_TPM_STS_0_ADDRESS_DEFAULT, TIS_PC_STS_READY); 583 584 return Status; 585 } 586 587 /** 588 This service enables the sending of commands to the TPM12. 589 590 @param[in] InputParameterBlockSize Size of the TPM12 input parameter block. 591 @param[in] InputParameterBlock Pointer to the TPM12 input parameter block. 592 @param[in,out] OutputParameterBlockSize Size of the TPM12 output parameter block. 593 @param[in] OutputParameterBlock Pointer to the TPM12 output parameter block. 594 595 @retval EFI_SUCCESS The command byte stream was successfully sent to 596 the device and a response was successfully received. 597 @retval EFI_DEVICE_ERROR The command was not successfully sent to the 598 device or a response was not successfully received 599 from the device. 600 @retval EFI_BUFFER_TOO_SMALL The output parameter block is too small. 601 **/ 602 EFI_STATUS 603 EFIAPI 604 Tpm12SubmitCommand ( 605 IN UINT32 InputParameterBlockSize, 606 IN UINT8 *InputParameterBlock, 607 IN OUT UINT32 *OutputParameterBlockSize, 608 IN UINT8 *OutputParameterBlock 609 ) 610 { 611 EFI_STATUS Status; 612 613 Status = TisPcSend (InputParameterBlock, InputParameterBlockSize); 614 if (!EFI_ERROR (Status)) { 615 Status = TisPcReceive (OutputParameterBlock, OutputParameterBlockSize); 616 } 617 return Status; 618 } 619