1 /** @file 2 Initialize TPM device and measure FVs before handing off control to DXE. 3 4 Copyright (c) 2005 - 2015, 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 17 #include <IndustryStandard/Tpm12.h> 18 #include <IndustryStandard/UefiTcgPlatform.h> 19 #include <Ppi/FirmwareVolumeInfo.h> 20 #include <Ppi/FirmwareVolumeInfo2.h> 21 #include <Ppi/LockPhysicalPresence.h> 22 #include <Ppi/TpmInitialized.h> 23 #include <Ppi/FirmwareVolume.h> 24 #include <Ppi/EndOfPeiPhase.h> 25 #include <Ppi/FirmwareVolumeInfoMeasurementExcluded.h> 26 27 #include <Guid/TcgEventHob.h> 28 #include <Guid/MeasuredFvHob.h> 29 #include <Guid/TpmInstance.h> 30 31 #include <Library/DebugLib.h> 32 #include <Library/BaseMemoryLib.h> 33 #include <Library/PeiServicesLib.h> 34 #include <Library/PeimEntryPoint.h> 35 #include <Library/TpmCommLib.h> 36 #include <Library/HobLib.h> 37 #include <Library/PcdLib.h> 38 #include <Library/PeiServicesTablePointerLib.h> 39 #include <Library/BaseLib.h> 40 #include <Library/MemoryAllocationLib.h> 41 #include <Library/ReportStatusCodeLib.h> 42 43 #include "TpmComm.h" 44 45 BOOLEAN mImageInMemory = FALSE; 46 47 EFI_PEI_PPI_DESCRIPTOR mTpmInitializedPpiList = { 48 EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST, 49 &gPeiTpmInitializedPpiGuid, 50 NULL 51 }; 52 53 EFI_PEI_PPI_DESCRIPTOR mTpmInitializationDonePpiList = { 54 EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST, 55 &gPeiTpmInitializationDonePpiGuid, 56 NULL 57 }; 58 59 EFI_PLATFORM_FIRMWARE_BLOB *mMeasuredBaseFvInfo; 60 UINT32 mMeasuredBaseFvIndex = 0; 61 62 EFI_PLATFORM_FIRMWARE_BLOB *mMeasuredChildFvInfo; 63 UINT32 mMeasuredChildFvIndex = 0; 64 65 EFI_PEI_FIRMWARE_VOLUME_INFO_MEASUREMENT_EXCLUDED_PPI *mMeasurementExcludedFvPpi; 66 67 /** 68 Lock physical presence if needed. 69 70 @param[in] PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation 71 @param[in] NotifyDescriptor Address of the notification descriptor data structure. 72 @param[in] Ppi Address of the PPI that was installed. 73 74 @retval EFI_SUCCESS Operation completed successfully. 75 76 **/ 77 EFI_STATUS 78 EFIAPI 79 PhysicalPresencePpiNotifyCallback ( 80 IN EFI_PEI_SERVICES **PeiServices, 81 IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor, 82 IN VOID *Ppi 83 ); 84 85 /** 86 Measure and record the Firmware Volum Information once FvInfoPPI install. 87 88 @param[in] PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation. 89 @param[in] NotifyDescriptor Address of the notification descriptor data structure. 90 @param[in] Ppi Address of the PPI that was installed. 91 92 @retval EFI_SUCCESS The FV Info is measured and recorded to TPM. 93 @return Others Fail to measure FV. 94 95 **/ 96 EFI_STATUS 97 EFIAPI 98 FirmwareVolmeInfoPpiNotifyCallback ( 99 IN EFI_PEI_SERVICES **PeiServices, 100 IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor, 101 IN VOID *Ppi 102 ); 103 104 /** 105 Record all measured Firmware Volum Information into a Guid Hob 106 107 @param[in] PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation. 108 @param[in] NotifyDescriptor Address of the notification descriptor data structure. 109 @param[in] Ppi Address of the PPI that was installed. 110 111 @retval EFI_SUCCESS The FV Info is measured and recorded to TPM. 112 @return Others Fail to measure FV. 113 114 **/ 115 EFI_STATUS 116 EFIAPI 117 EndofPeiSignalNotifyCallBack ( 118 IN EFI_PEI_SERVICES **PeiServices, 119 IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor, 120 IN VOID *Ppi 121 ); 122 123 EFI_PEI_NOTIFY_DESCRIPTOR mNotifyList[] = { 124 { 125 EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK, 126 &gPeiLockPhysicalPresencePpiGuid, 127 PhysicalPresencePpiNotifyCallback 128 }, 129 { 130 EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK, 131 &gEfiPeiFirmwareVolumeInfoPpiGuid, 132 FirmwareVolmeInfoPpiNotifyCallback 133 }, 134 { 135 EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK, 136 &gEfiPeiFirmwareVolumeInfo2PpiGuid, 137 FirmwareVolmeInfoPpiNotifyCallback 138 }, 139 { 140 (EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST), 141 &gEfiEndOfPeiSignalPpiGuid, 142 EndofPeiSignalNotifyCallBack 143 } 144 }; 145 146 /** 147 Record all measured Firmware Volum Information into a Guid Hob 148 Guid Hob payload layout is 149 150 UINT32 *************************** FIRMWARE_BLOB number 151 EFI_PLATFORM_FIRMWARE_BLOB******** BLOB Array 152 153 @param[in] PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation. 154 @param[in] NotifyDescriptor Address of the notification descriptor data structure. 155 @param[in] Ppi Address of the PPI that was installed. 156 157 @retval EFI_SUCCESS The FV Info is measured and recorded to TPM. 158 @return Others Fail to measure FV. 159 160 **/ 161 EFI_STATUS 162 EFIAPI 163 EndofPeiSignalNotifyCallBack ( 164 IN EFI_PEI_SERVICES **PeiServices, 165 IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor, 166 IN VOID *Ppi 167 ) 168 { 169 MEASURED_HOB_DATA *MeasuredHobData; 170 171 MeasuredHobData = NULL; 172 173 // 174 // Create a Guid hob to save all measured Fv 175 // 176 MeasuredHobData = BuildGuidHob( 177 &gMeasuredFvHobGuid, 178 sizeof(UINTN) + sizeof(EFI_PLATFORM_FIRMWARE_BLOB) * (mMeasuredBaseFvIndex + mMeasuredChildFvIndex) 179 ); 180 181 if (MeasuredHobData != NULL){ 182 // 183 // Save measured FV info enty number 184 // 185 MeasuredHobData->Num = mMeasuredBaseFvIndex + mMeasuredChildFvIndex; 186 187 // 188 // Save measured base Fv info 189 // 190 CopyMem (MeasuredHobData->MeasuredFvBuf, mMeasuredBaseFvInfo, sizeof(EFI_PLATFORM_FIRMWARE_BLOB) * (mMeasuredBaseFvIndex)); 191 192 // 193 // Save measured child Fv info 194 // 195 CopyMem (&MeasuredHobData->MeasuredFvBuf[mMeasuredBaseFvIndex] , mMeasuredChildFvInfo, sizeof(EFI_PLATFORM_FIRMWARE_BLOB) * (mMeasuredChildFvIndex)); 196 } 197 198 return EFI_SUCCESS; 199 } 200 201 /** 202 Do a hash operation on a data buffer, extend a specific TPM PCR with the hash result, 203 and build a GUIDed HOB recording the event which will be passed to the DXE phase and 204 added into the Event Log. 205 206 @param[in] PeiServices Describes the list of possible PEI Services. 207 @param[in] HashData Physical address of the start of the data buffer 208 to be hashed, extended, and logged. 209 @param[in] HashDataLen The length, in bytes, of the buffer referenced by HashData. 210 @param[in] TpmHandle TPM handle. 211 @param[in] NewEventHdr Pointer to a TCG_PCR_EVENT_HDR data structure. 212 @param[in] NewEventData Pointer to the new event data. 213 214 @retval EFI_SUCCESS Operation completed successfully. 215 @retval EFI_OUT_OF_RESOURCES No enough memory to log the new event. 216 @retval EFI_DEVICE_ERROR The command was unsuccessful. 217 218 **/ 219 EFI_STATUS 220 HashLogExtendEvent ( 221 IN EFI_PEI_SERVICES **PeiServices, 222 IN UINT8 *HashData, 223 IN UINTN HashDataLen, 224 IN TIS_TPM_HANDLE TpmHandle, 225 IN TCG_PCR_EVENT_HDR *NewEventHdr, 226 IN UINT8 *NewEventData 227 ) 228 { 229 EFI_STATUS Status; 230 VOID *HobData; 231 232 if (GetFirstGuidHob (&gTpmErrorHobGuid) != NULL) { 233 return EFI_DEVICE_ERROR; 234 } 235 236 HobData = NULL; 237 if (HashDataLen != 0) { 238 Status = TpmCommHashAll ( 239 HashData, 240 HashDataLen, 241 &NewEventHdr->Digest 242 ); 243 if (EFI_ERROR (Status)) { 244 goto Done; 245 } 246 } 247 248 Status = TpmCommExtend ( 249 PeiServices, 250 TpmHandle, 251 &NewEventHdr->Digest, 252 NewEventHdr->PCRIndex, 253 NULL 254 ); 255 if (EFI_ERROR (Status)) { 256 goto Done; 257 } 258 259 HobData = BuildGuidHob ( 260 &gTcgEventEntryHobGuid, 261 sizeof (*NewEventHdr) + NewEventHdr->EventSize 262 ); 263 if (HobData == NULL) { 264 Status = EFI_OUT_OF_RESOURCES; 265 goto Done; 266 } 267 268 CopyMem (HobData, NewEventHdr, sizeof (*NewEventHdr)); 269 HobData = (VOID *) ((UINT8*)HobData + sizeof (*NewEventHdr)); 270 CopyMem (HobData, NewEventData, NewEventHdr->EventSize); 271 272 Done: 273 if ((Status == EFI_DEVICE_ERROR) || (Status == EFI_TIMEOUT)) { 274 DEBUG ((EFI_D_ERROR, "HashLogExtendEvent - %r. Disable TPM.\n", Status)); 275 BuildGuidHob (&gTpmErrorHobGuid,0); 276 REPORT_STATUS_CODE ( 277 EFI_ERROR_CODE | EFI_ERROR_MINOR, 278 (PcdGet32 (PcdStatusCodeSubClassTpmDevice) | EFI_P_EC_INTERFACE_ERROR) 279 ); 280 Status = EFI_DEVICE_ERROR; 281 } 282 return Status; 283 } 284 285 /** 286 Measure CRTM version. 287 288 @param[in] PeiServices Describes the list of possible PEI Services. 289 @param[in] TpmHandle TPM handle. 290 291 @retval EFI_SUCCESS Operation completed successfully. 292 @retval EFI_OUT_OF_RESOURCES No enough memory to log the new event. 293 @retval EFI_DEVICE_ERROR The command was unsuccessful. 294 295 **/ 296 EFI_STATUS 297 EFIAPI 298 MeasureCRTMVersion ( 299 IN EFI_PEI_SERVICES **PeiServices, 300 IN TIS_TPM_HANDLE TpmHandle 301 ) 302 { 303 TCG_PCR_EVENT_HDR TcgEventHdr; 304 305 // 306 // Use FirmwareVersion string to represent CRTM version. 307 // OEMs should get real CRTM version string and measure it. 308 // 309 310 TcgEventHdr.PCRIndex = 0; 311 TcgEventHdr.EventType = EV_S_CRTM_VERSION; 312 TcgEventHdr.EventSize = (UINT32) StrSize((CHAR16*)PcdGetPtr (PcdFirmwareVersionString)); 313 314 return HashLogExtendEvent ( 315 PeiServices, 316 (UINT8*)PcdGetPtr (PcdFirmwareVersionString), 317 TcgEventHdr.EventSize, 318 TpmHandle, 319 &TcgEventHdr, 320 (UINT8*)PcdGetPtr (PcdFirmwareVersionString) 321 ); 322 } 323 324 /** 325 Measure FV image. 326 Add it into the measured FV list after the FV is measured successfully. 327 328 @param[in] FvBase Base address of FV image. 329 @param[in] FvLength Length of FV image. 330 331 @retval EFI_SUCCESS Fv image is measured successfully 332 or it has been already measured. 333 @retval EFI_OUT_OF_RESOURCES No enough memory to log the new event. 334 @retval EFI_DEVICE_ERROR The command was unsuccessful. 335 336 **/ 337 EFI_STATUS 338 EFIAPI 339 MeasureFvImage ( 340 IN EFI_PHYSICAL_ADDRESS FvBase, 341 IN UINT64 FvLength 342 ) 343 { 344 UINT32 Index; 345 EFI_STATUS Status; 346 EFI_PLATFORM_FIRMWARE_BLOB FvBlob; 347 TCG_PCR_EVENT_HDR TcgEventHdr; 348 TIS_TPM_HANDLE TpmHandle; 349 350 TpmHandle = (TIS_TPM_HANDLE) (UINTN) TPM_BASE_ADDRESS; 351 352 // 353 // Check if it is in Excluded FV list 354 // 355 if (mMeasurementExcludedFvPpi != NULL) { 356 for (Index = 0; Index < mMeasurementExcludedFvPpi->Count; Index ++) { 357 if (mMeasurementExcludedFvPpi->Fv[Index].FvBase == FvBase) { 358 DEBUG ((DEBUG_INFO, "The FV which is excluded by TcgPei starts at: 0x%x\n", FvBase)); 359 DEBUG ((DEBUG_INFO, "The FV which is excluded by TcgPei has the size: 0x%x\n", FvLength)); 360 return EFI_SUCCESS; 361 } 362 } 363 } 364 365 // 366 // Check whether FV is in the measured FV list. 367 // 368 for (Index = 0; Index < mMeasuredBaseFvIndex; Index ++) { 369 if (mMeasuredBaseFvInfo[Index].BlobBase == FvBase) { 370 return EFI_SUCCESS; 371 } 372 } 373 374 // 375 // Measure and record the FV to the TPM 376 // 377 FvBlob.BlobBase = FvBase; 378 FvBlob.BlobLength = FvLength; 379 380 DEBUG ((DEBUG_INFO, "The FV which is measured by TcgPei starts at: 0x%x\n", FvBlob.BlobBase)); 381 DEBUG ((DEBUG_INFO, "The FV which is measured by TcgPei has the size: 0x%x\n", FvBlob.BlobLength)); 382 383 TcgEventHdr.PCRIndex = 0; 384 TcgEventHdr.EventType = EV_EFI_PLATFORM_FIRMWARE_BLOB; 385 TcgEventHdr.EventSize = sizeof (FvBlob); 386 387 Status = HashLogExtendEvent ( 388 (EFI_PEI_SERVICES **) GetPeiServicesTablePointer(), 389 (UINT8*) (UINTN) FvBlob.BlobBase, 390 (UINTN) FvBlob.BlobLength, 391 TpmHandle, 392 &TcgEventHdr, 393 (UINT8*) &FvBlob 394 ); 395 396 // 397 // Add new FV into the measured FV list. 398 // 399 ASSERT (mMeasuredBaseFvIndex < PcdGet32 (PcdPeiCoreMaxFvSupported)); 400 if (mMeasuredBaseFvIndex < PcdGet32 (PcdPeiCoreMaxFvSupported)) { 401 mMeasuredBaseFvInfo[mMeasuredBaseFvIndex].BlobBase = FvBase; 402 mMeasuredBaseFvInfo[mMeasuredBaseFvIndex].BlobLength = FvLength; 403 mMeasuredBaseFvIndex++; 404 } 405 406 return Status; 407 } 408 409 /** 410 Measure main BIOS. 411 412 @param[in] PeiServices Describes the list of possible PEI Services. 413 @param[in] TpmHandle TPM handle. 414 415 @retval EFI_SUCCESS Operation completed successfully. 416 @retval EFI_OUT_OF_RESOURCES No enough memory to log the new event. 417 @retval EFI_DEVICE_ERROR The command was unsuccessful. 418 419 **/ 420 EFI_STATUS 421 EFIAPI 422 MeasureMainBios ( 423 IN EFI_PEI_SERVICES **PeiServices, 424 IN TIS_TPM_HANDLE TpmHandle 425 ) 426 { 427 EFI_STATUS Status; 428 UINT32 FvInstances; 429 EFI_PEI_FV_HANDLE VolumeHandle; 430 EFI_FV_INFO VolumeInfo; 431 EFI_PEI_FIRMWARE_VOLUME_PPI *FvPpi; 432 433 FvInstances = 0; 434 while (TRUE) { 435 // 436 // Traverse all firmware volume instances of Static Core Root of Trust for Measurement 437 // (S-CRTM), this firmware volume measure policy can be modified/enhanced by special 438 // platform for special CRTM TPM measuring. 439 // 440 Status = PeiServicesFfsFindNextVolume (FvInstances, &VolumeHandle); 441 if (EFI_ERROR (Status)) { 442 break; 443 } 444 445 // 446 // Measure and record the firmware volume that is dispatched by PeiCore 447 // 448 Status = PeiServicesFfsGetVolumeInfo (VolumeHandle, &VolumeInfo); 449 ASSERT_EFI_ERROR (Status); 450 // 451 // Locate the corresponding FV_PPI according to founded FV's format guid 452 // 453 Status = PeiServicesLocatePpi ( 454 &VolumeInfo.FvFormat, 455 0, 456 NULL, 457 (VOID**)&FvPpi 458 ); 459 if (!EFI_ERROR (Status)) { 460 MeasureFvImage ((EFI_PHYSICAL_ADDRESS) (UINTN) VolumeInfo.FvStart, VolumeInfo.FvSize); 461 } 462 463 FvInstances++; 464 } 465 466 return EFI_SUCCESS; 467 } 468 469 /** 470 Measure and record the Firmware Volum Information once FvInfoPPI install. 471 472 @param[in] PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation. 473 @param[in] NotifyDescriptor Address of the notification descriptor data structure. 474 @param[in] Ppi Address of the PPI that was installed. 475 476 @retval EFI_SUCCESS The FV Info is measured and recorded to TPM. 477 @return Others Fail to measure FV. 478 479 **/ 480 EFI_STATUS 481 EFIAPI 482 FirmwareVolmeInfoPpiNotifyCallback ( 483 IN EFI_PEI_SERVICES **PeiServices, 484 IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor, 485 IN VOID *Ppi 486 ) 487 { 488 EFI_PEI_FIRMWARE_VOLUME_INFO_PPI *Fv; 489 EFI_STATUS Status; 490 EFI_PEI_FIRMWARE_VOLUME_PPI *FvPpi; 491 UINTN Index; 492 493 Fv = (EFI_PEI_FIRMWARE_VOLUME_INFO_PPI *) Ppi; 494 495 // 496 // The PEI Core can not dispatch or load files from memory mapped FVs that do not support FvPpi. 497 // 498 Status = PeiServicesLocatePpi ( 499 &Fv->FvFormat, 500 0, 501 NULL, 502 (VOID**)&FvPpi 503 ); 504 if (EFI_ERROR (Status)) { 505 return EFI_SUCCESS; 506 } 507 508 // 509 // This is an FV from an FFS file, and the parent FV must have already been measured, 510 // No need to measure twice, so just record the FV and return 511 // 512 if (Fv->ParentFvName != NULL || Fv->ParentFileName != NULL ) { 513 514 ASSERT (mMeasuredChildFvIndex < PcdGet32 (PcdPeiCoreMaxFvSupported)); 515 if (mMeasuredChildFvIndex < PcdGet32 (PcdPeiCoreMaxFvSupported)) { 516 // 517 // Check whether FV is in the measured child FV list. 518 // 519 for (Index = 0; Index < mMeasuredChildFvIndex; Index++) { 520 if (mMeasuredChildFvInfo[Index].BlobBase == (EFI_PHYSICAL_ADDRESS) (UINTN) Fv->FvInfo) { 521 return EFI_SUCCESS; 522 } 523 } 524 mMeasuredChildFvInfo[mMeasuredChildFvIndex].BlobBase = (EFI_PHYSICAL_ADDRESS) (UINTN) Fv->FvInfo; 525 mMeasuredChildFvInfo[mMeasuredChildFvIndex].BlobLength = Fv->FvInfoSize; 526 mMeasuredChildFvIndex++; 527 } 528 return EFI_SUCCESS; 529 } 530 531 return MeasureFvImage ((EFI_PHYSICAL_ADDRESS) (UINTN) Fv->FvInfo, Fv->FvInfoSize); 532 } 533 534 /** 535 Set physicalPresenceLifetimeLock, physicalPresenceHWEnable and physicalPresenceCMDEnable bit by corresponding PCDs. 536 And lock physical presence if needed. 537 538 @param[in] PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation 539 @param[in] NotifyDescriptor Address of the notification descriptor data structure. 540 @param[in] Ppi Address of the PPI that was installed. 541 542 @retval EFI_SUCCESS Operation completed successfully. 543 @retval EFI_ABORTED physicalPresenceCMDEnable is locked. 544 @retval EFI_DEVICE_ERROR The command was unsuccessful. 545 546 **/ 547 EFI_STATUS 548 EFIAPI 549 PhysicalPresencePpiNotifyCallback ( 550 IN EFI_PEI_SERVICES **PeiServices, 551 IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor, 552 IN VOID *Ppi 553 ) 554 { 555 EFI_STATUS Status; 556 PEI_LOCK_PHYSICAL_PRESENCE_PPI *LockPhysicalPresencePpi; 557 BOOLEAN LifetimeLock; 558 BOOLEAN CmdEnable; 559 TIS_TPM_HANDLE TpmHandle; 560 TPM_PHYSICAL_PRESENCE PhysicalPresenceValue; 561 562 TpmHandle = (TIS_TPM_HANDLE) (UINTN) TPM_BASE_ADDRESS; 563 564 Status = TpmCommGetCapability (PeiServices, TpmHandle, NULL, &LifetimeLock, &CmdEnable); 565 if (EFI_ERROR (Status)) { 566 return Status; 567 } 568 569 // 570 // 1. Set physicalPresenceLifetimeLock, physicalPresenceHWEnable and physicalPresenceCMDEnable bit by PCDs. 571 // 572 if (PcdGetBool (PcdPhysicalPresenceLifetimeLock) && !LifetimeLock) { 573 // 574 // Lock TPM LifetimeLock is required, and LifetimeLock is not locked yet. 575 // 576 PhysicalPresenceValue = TPM_PHYSICAL_PRESENCE_LIFETIME_LOCK; 577 578 if (PcdGetBool (PcdPhysicalPresenceCmdEnable)) { 579 PhysicalPresenceValue |= TPM_PHYSICAL_PRESENCE_CMD_ENABLE; 580 CmdEnable = TRUE; 581 } else { 582 PhysicalPresenceValue |= TPM_PHYSICAL_PRESENCE_CMD_DISABLE; 583 CmdEnable = FALSE; 584 } 585 586 if (PcdGetBool (PcdPhysicalPresenceHwEnable)) { 587 PhysicalPresenceValue |= TPM_PHYSICAL_PRESENCE_HW_ENABLE; 588 } else { 589 PhysicalPresenceValue |= TPM_PHYSICAL_PRESENCE_HW_DISABLE; 590 } 591 592 Status = TpmCommPhysicalPresence ( 593 PeiServices, 594 TpmHandle, 595 PhysicalPresenceValue 596 ); 597 if (EFI_ERROR (Status)) { 598 return Status; 599 } 600 } 601 602 // 603 // 2. Lock physical presence if it is required. 604 // 605 LockPhysicalPresencePpi = (PEI_LOCK_PHYSICAL_PRESENCE_PPI *) Ppi; 606 if (!LockPhysicalPresencePpi->LockPhysicalPresence ((CONST EFI_PEI_SERVICES**) PeiServices)) { 607 return EFI_SUCCESS; 608 } 609 610 if (!CmdEnable) { 611 if (LifetimeLock) { 612 // 613 // physicalPresenceCMDEnable is locked, can't change. 614 // 615 return EFI_ABORTED; 616 } 617 618 // 619 // Enable physical presence command 620 // It is necessary in order to lock physical presence 621 // 622 Status = TpmCommPhysicalPresence ( 623 PeiServices, 624 TpmHandle, 625 TPM_PHYSICAL_PRESENCE_CMD_ENABLE 626 ); 627 if (EFI_ERROR (Status)) { 628 return Status; 629 } 630 } 631 632 // 633 // Lock physical presence 634 // 635 Status = TpmCommPhysicalPresence ( 636 PeiServices, 637 TpmHandle, 638 TPM_PHYSICAL_PRESENCE_LOCK 639 ); 640 return Status; 641 } 642 643 /** 644 Check if TPM chip is activeated or not. 645 646 @param[in] PeiServices Describes the list of possible PEI Services. 647 @param[in] TpmHandle TPM handle. 648 649 @retval TRUE TPM is activated. 650 @retval FALSE TPM is deactivated. 651 652 **/ 653 BOOLEAN 654 EFIAPI 655 IsTpmUsable ( 656 IN EFI_PEI_SERVICES **PeiServices, 657 IN TIS_TPM_HANDLE TpmHandle 658 ) 659 { 660 EFI_STATUS Status; 661 BOOLEAN Deactivated; 662 663 Status = TpmCommGetCapability (PeiServices, TpmHandle, &Deactivated, NULL, NULL); 664 if (EFI_ERROR (Status)) { 665 return FALSE; 666 } 667 return (BOOLEAN)(!Deactivated); 668 } 669 670 /** 671 Do measurement after memory is ready. 672 673 @param[in] PeiServices Describes the list of possible PEI Services. 674 675 @retval EFI_SUCCESS Operation completed successfully. 676 @retval EFI_OUT_OF_RESOURCES No enough memory to log the new event. 677 @retval EFI_DEVICE_ERROR The command was unsuccessful. 678 679 **/ 680 EFI_STATUS 681 EFIAPI 682 PeimEntryMP ( 683 IN EFI_PEI_SERVICES **PeiServices 684 ) 685 { 686 EFI_STATUS Status; 687 TIS_TPM_HANDLE TpmHandle; 688 689 Status = PeiServicesLocatePpi ( 690 &gEfiPeiFirmwareVolumeInfoMeasurementExcludedPpiGuid, 691 0, 692 NULL, 693 (VOID**)&mMeasurementExcludedFvPpi 694 ); 695 // Do not check status, because it is optional 696 697 mMeasuredBaseFvInfo = (EFI_PLATFORM_FIRMWARE_BLOB *) AllocateZeroPool (sizeof (EFI_PLATFORM_FIRMWARE_BLOB) * PcdGet32 (PcdPeiCoreMaxFvSupported)); 698 ASSERT (mMeasuredBaseFvInfo != NULL); 699 mMeasuredChildFvInfo = (EFI_PLATFORM_FIRMWARE_BLOB *) AllocateZeroPool (sizeof (EFI_PLATFORM_FIRMWARE_BLOB) * PcdGet32 (PcdPeiCoreMaxFvSupported)); 700 ASSERT (mMeasuredChildFvInfo != NULL); 701 702 TpmHandle = (TIS_TPM_HANDLE)(UINTN)TPM_BASE_ADDRESS; 703 Status = TisPcRequestUseTpm ((TIS_PC_REGISTERS_PTR)TpmHandle); 704 if (EFI_ERROR (Status)) { 705 return Status; 706 } 707 708 if (IsTpmUsable (PeiServices, TpmHandle)) { 709 if (PcdGet8 (PcdTpmScrtmPolicy) == 1) { 710 Status = MeasureCRTMVersion (PeiServices, TpmHandle); 711 } 712 713 Status = MeasureMainBios (PeiServices, TpmHandle); 714 } 715 716 // 717 // Post callbacks: 718 // 1). for the FvInfoPpi services to measure and record 719 // the additional Fvs to TPM 720 // 2). for the OperatorPresencePpi service to determine whether to 721 // lock the TPM 722 // 723 Status = PeiServicesNotifyPpi (&mNotifyList[0]); 724 ASSERT_EFI_ERROR (Status); 725 726 return Status; 727 } 728 729 /** 730 Entry point of this module. 731 732 @param[in] FileHandle Handle of the file being invoked. 733 @param[in] PeiServices Describes the list of possible PEI Services. 734 735 @return Status. 736 737 **/ 738 EFI_STATUS 739 EFIAPI 740 PeimEntryMA ( 741 IN EFI_PEI_FILE_HANDLE FileHandle, 742 IN CONST EFI_PEI_SERVICES **PeiServices 743 ) 744 { 745 EFI_STATUS Status; 746 EFI_STATUS Status2; 747 EFI_BOOT_MODE BootMode; 748 TIS_TPM_HANDLE TpmHandle; 749 750 if (!CompareGuid (PcdGetPtr(PcdTpmInstanceGuid), &gEfiTpmDeviceInstanceTpm12Guid)){ 751 DEBUG ((EFI_D_ERROR, "No TPM12 instance required!\n")); 752 return EFI_UNSUPPORTED; 753 } 754 755 if (GetFirstGuidHob (&gTpmErrorHobGuid) != NULL) { 756 DEBUG ((EFI_D_ERROR, "TPM error!\n")); 757 return EFI_DEVICE_ERROR; 758 } 759 760 // 761 // Initialize TPM device 762 // 763 Status = PeiServicesGetBootMode (&BootMode); 764 ASSERT_EFI_ERROR (Status); 765 766 // 767 // In S3 path, skip shadow logic. no measurement is required 768 // 769 if (BootMode != BOOT_ON_S3_RESUME) { 770 Status = (**PeiServices).RegisterForShadow(FileHandle); 771 if (Status == EFI_ALREADY_STARTED) { 772 mImageInMemory = TRUE; 773 } else if (Status == EFI_NOT_FOUND) { 774 ASSERT_EFI_ERROR (Status); 775 } 776 } 777 778 if (!mImageInMemory) { 779 TpmHandle = (TIS_TPM_HANDLE)(UINTN)TPM_BASE_ADDRESS; 780 Status = TisPcRequestUseTpm ((TIS_PC_REGISTERS_PTR)TpmHandle); 781 if (EFI_ERROR (Status)) { 782 DEBUG ((DEBUG_ERROR, "TPM not detected!\n")); 783 goto Done; 784 } 785 786 if (PcdGet8 (PcdTpmInitializationPolicy) == 1) { 787 Status = TpmCommStartup ((EFI_PEI_SERVICES**)PeiServices, TpmHandle, BootMode); 788 if (EFI_ERROR (Status) ) { 789 goto Done; 790 } 791 } 792 793 // 794 // TpmSelfTest is optional on S3 path, skip it to save S3 time 795 // 796 if (BootMode != BOOT_ON_S3_RESUME) { 797 Status = TpmCommContinueSelfTest ((EFI_PEI_SERVICES**)PeiServices, TpmHandle); 798 if (EFI_ERROR (Status)) { 799 goto Done; 800 } 801 } 802 803 // 804 // Only intall TpmInitializedPpi on success 805 // 806 Status = PeiServicesInstallPpi (&mTpmInitializedPpiList); 807 ASSERT_EFI_ERROR (Status); 808 } 809 810 if (mImageInMemory) { 811 Status = PeimEntryMP ((EFI_PEI_SERVICES**)PeiServices); 812 return Status; 813 } 814 815 Done: 816 if (EFI_ERROR (Status)) { 817 DEBUG ((EFI_D_ERROR, "TPM error! Build Hob\n")); 818 BuildGuidHob (&gTpmErrorHobGuid,0); 819 REPORT_STATUS_CODE ( 820 EFI_ERROR_CODE | EFI_ERROR_MINOR, 821 (PcdGet32 (PcdStatusCodeSubClassTpmDevice) | EFI_P_EC_INTERFACE_ERROR) 822 ); 823 } 824 // 825 // Always intall TpmInitializationDonePpi no matter success or fail. 826 // Other driver can know TPM initialization state by TpmInitializedPpi. 827 // 828 Status2 = PeiServicesInstallPpi (&mTpmInitializationDonePpiList); 829 ASSERT_EFI_ERROR (Status2); 830 831 return Status; 832 } 833