1/** @file 2 Initialize TPM device and measure FVs before handing off control to DXE. 3 4Copyright (c) 2005 - 2016, Intel Corporation. All rights reserved.<BR> 5This program and the accompanying materials 6are licensed and made available under the terms and conditions of the BSD License 7which accompanies this distribution. The full text of the license may be found at 8http://opensource.org/licenses/bsd-license.php 9 10THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, 11WITHOUT 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/HobLib.h> 36#include <Library/PcdLib.h> 37#include <Library/PeiServicesTablePointerLib.h> 38#include <Library/BaseLib.h> 39#include <Library/MemoryAllocationLib.h> 40#include <Library/ReportStatusCodeLib.h> 41#include <Library/Tpm12DeviceLib.h> 42#include <Library/Tpm12CommandLib.h> 43#include <Library/BaseCryptLib.h> 44 45BOOLEAN mImageInMemory = FALSE; 46 47EFI_PEI_PPI_DESCRIPTOR mTpmInitializedPpiList = { 48 EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST, 49 &gPeiTpmInitializedPpiGuid, 50 NULL 51}; 52 53EFI_PEI_PPI_DESCRIPTOR mTpmInitializationDonePpiList = { 54 EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST, 55 &gPeiTpmInitializationDonePpiGuid, 56 NULL 57}; 58 59EFI_PLATFORM_FIRMWARE_BLOB *mMeasuredBaseFvInfo; 60UINT32 mMeasuredBaseFvIndex = 0; 61 62EFI_PLATFORM_FIRMWARE_BLOB *mMeasuredChildFvInfo; 63UINT32 mMeasuredChildFvIndex = 0; 64 65EFI_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**/ 77EFI_STATUS 78EFIAPI 79PhysicalPresencePpiNotifyCallback ( 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**/ 96EFI_STATUS 97EFIAPI 98FirmwareVolmeInfoPpiNotifyCallback ( 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**/ 115EFI_STATUS 116EFIAPI 117EndofPeiSignalNotifyCallBack ( 118 IN EFI_PEI_SERVICES **PeiServices, 119 IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor, 120 IN VOID *Ppi 121 ); 122 123EFI_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**/ 161EFI_STATUS 162EFIAPI 163EndofPeiSignalNotifyCallBack ( 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/** 202Single function calculates SHA1 digest value for all raw data. It 203combines Sha1Init(), Sha1Update() and Sha1Final(). 204 205@param[in] Data Raw data to be digested. 206@param[in] DataLen Size of the raw data. 207@param[out] Digest Pointer to a buffer that stores the final digest. 208 209@retval EFI_SUCCESS Always successfully calculate the final digest. 210**/ 211EFI_STATUS 212EFIAPI 213TpmCommHashAll ( 214 IN CONST UINT8 *Data, 215 IN UINTN DataLen, 216 OUT TPM_DIGEST *Digest 217 ) 218{ 219 VOID *Sha1Ctx; 220 UINTN CtxSize; 221 222 CtxSize = Sha1GetContextSize (); 223 Sha1Ctx = AllocatePool (CtxSize); 224 ASSERT (Sha1Ctx != NULL); 225 226 Sha1Init (Sha1Ctx); 227 Sha1Update (Sha1Ctx, Data, DataLen); 228 Sha1Final (Sha1Ctx, (UINT8 *)Digest); 229 230 FreePool (Sha1Ctx); 231 232 return EFI_SUCCESS; 233} 234 235/** 236 Do a hash operation on a data buffer, extend a specific TPM PCR with the hash result, 237 and build a GUIDed HOB recording the event which will be passed to the DXE phase and 238 added into the Event Log. 239 240 @param[in] PeiServices Describes the list of possible PEI Services. 241 @param[in] HashData Physical address of the start of the data buffer 242 to be hashed, extended, and logged. 243 @param[in] HashDataLen The length, in bytes, of the buffer referenced by HashData. 244 @param[in] NewEventHdr Pointer to a TCG_PCR_EVENT_HDR data structure. 245 @param[in] NewEventData Pointer to the new event data. 246 247 @retval EFI_SUCCESS Operation completed successfully. 248 @retval EFI_OUT_OF_RESOURCES No enough memory to log the new event. 249 @retval EFI_DEVICE_ERROR The command was unsuccessful. 250 251**/ 252EFI_STATUS 253HashLogExtendEvent ( 254 IN EFI_PEI_SERVICES **PeiServices, 255 IN UINT8 *HashData, 256 IN UINTN HashDataLen, 257 IN TCG_PCR_EVENT_HDR *NewEventHdr, 258 IN UINT8 *NewEventData 259 ) 260{ 261 EFI_STATUS Status; 262 VOID *HobData; 263 264 if (GetFirstGuidHob (&gTpmErrorHobGuid) != NULL) { 265 return EFI_DEVICE_ERROR; 266 } 267 268 HobData = NULL; 269 if (HashDataLen != 0) { 270 Status = TpmCommHashAll ( 271 HashData, 272 HashDataLen, 273 &NewEventHdr->Digest 274 ); 275 if (EFI_ERROR (Status)) { 276 goto Done; 277 } 278 } 279 280 Status = Tpm12Extend ( 281 &NewEventHdr->Digest, 282 NewEventHdr->PCRIndex, 283 NULL 284 ); 285 if (EFI_ERROR (Status)) { 286 goto Done; 287 } 288 289 HobData = BuildGuidHob ( 290 &gTcgEventEntryHobGuid, 291 sizeof (*NewEventHdr) + NewEventHdr->EventSize 292 ); 293 if (HobData == NULL) { 294 Status = EFI_OUT_OF_RESOURCES; 295 goto Done; 296 } 297 298 CopyMem (HobData, NewEventHdr, sizeof (*NewEventHdr)); 299 HobData = (VOID *) ((UINT8*)HobData + sizeof (*NewEventHdr)); 300 CopyMem (HobData, NewEventData, NewEventHdr->EventSize); 301 302Done: 303 if ((Status == EFI_DEVICE_ERROR) || (Status == EFI_TIMEOUT)) { 304 DEBUG ((EFI_D_ERROR, "HashLogExtendEvent - %r. Disable TPM.\n", Status)); 305 BuildGuidHob (&gTpmErrorHobGuid,0); 306 REPORT_STATUS_CODE ( 307 EFI_ERROR_CODE | EFI_ERROR_MINOR, 308 (PcdGet32 (PcdStatusCodeSubClassTpmDevice) | EFI_P_EC_INTERFACE_ERROR) 309 ); 310 Status = EFI_DEVICE_ERROR; 311 } 312 return Status; 313} 314 315/** 316 Measure CRTM version. 317 318 @param[in] PeiServices Describes the list of possible PEI Services. 319 320 @retval EFI_SUCCESS Operation completed successfully. 321 @retval EFI_OUT_OF_RESOURCES No enough memory to log the new event. 322 @retval EFI_DEVICE_ERROR The command was unsuccessful. 323 324**/ 325EFI_STATUS 326EFIAPI 327MeasureCRTMVersion ( 328 IN EFI_PEI_SERVICES **PeiServices 329 ) 330{ 331 TCG_PCR_EVENT_HDR TcgEventHdr; 332 333 // 334 // Use FirmwareVersion string to represent CRTM version. 335 // OEMs should get real CRTM version string and measure it. 336 // 337 338 TcgEventHdr.PCRIndex = 0; 339 TcgEventHdr.EventType = EV_S_CRTM_VERSION; 340 TcgEventHdr.EventSize = (UINT32) StrSize((CHAR16*)PcdGetPtr (PcdFirmwareVersionString)); 341 342 return HashLogExtendEvent ( 343 PeiServices, 344 (UINT8*)PcdGetPtr (PcdFirmwareVersionString), 345 TcgEventHdr.EventSize, 346 &TcgEventHdr, 347 (UINT8*)PcdGetPtr (PcdFirmwareVersionString) 348 ); 349} 350 351/** 352 Measure FV image. 353 Add it into the measured FV list after the FV is measured successfully. 354 355 @param[in] FvBase Base address of FV image. 356 @param[in] FvLength Length of FV image. 357 358 @retval EFI_SUCCESS Fv image is measured successfully 359 or it has been already measured. 360 @retval EFI_OUT_OF_RESOURCES No enough memory to log the new event. 361 @retval EFI_DEVICE_ERROR The command was unsuccessful. 362 363**/ 364EFI_STATUS 365EFIAPI 366MeasureFvImage ( 367 IN EFI_PHYSICAL_ADDRESS FvBase, 368 IN UINT64 FvLength 369 ) 370{ 371 UINT32 Index; 372 EFI_STATUS Status; 373 EFI_PLATFORM_FIRMWARE_BLOB FvBlob; 374 TCG_PCR_EVENT_HDR TcgEventHdr; 375 376 // 377 // Check if it is in Excluded FV list 378 // 379 if (mMeasurementExcludedFvPpi != NULL) { 380 for (Index = 0; Index < mMeasurementExcludedFvPpi->Count; Index ++) { 381 if (mMeasurementExcludedFvPpi->Fv[Index].FvBase == FvBase) { 382 DEBUG ((DEBUG_INFO, "The FV which is excluded by TcgPei starts at: 0x%x\n", FvBase)); 383 DEBUG ((DEBUG_INFO, "The FV which is excluded by TcgPei has the size: 0x%x\n", FvLength)); 384 return EFI_SUCCESS; 385 } 386 } 387 } 388 389 // 390 // Check whether FV is in the measured FV list. 391 // 392 for (Index = 0; Index < mMeasuredBaseFvIndex; Index ++) { 393 if (mMeasuredBaseFvInfo[Index].BlobBase == FvBase) { 394 return EFI_SUCCESS; 395 } 396 } 397 398 // 399 // Measure and record the FV to the TPM 400 // 401 FvBlob.BlobBase = FvBase; 402 FvBlob.BlobLength = FvLength; 403 404 DEBUG ((DEBUG_INFO, "The FV which is measured by TcgPei starts at: 0x%x\n", FvBlob.BlobBase)); 405 DEBUG ((DEBUG_INFO, "The FV which is measured by TcgPei has the size: 0x%x\n", FvBlob.BlobLength)); 406 407 TcgEventHdr.PCRIndex = 0; 408 TcgEventHdr.EventType = EV_EFI_PLATFORM_FIRMWARE_BLOB; 409 TcgEventHdr.EventSize = sizeof (FvBlob); 410 411 Status = HashLogExtendEvent ( 412 (EFI_PEI_SERVICES **) GetPeiServicesTablePointer(), 413 (UINT8*) (UINTN) FvBlob.BlobBase, 414 (UINTN) FvBlob.BlobLength, 415 &TcgEventHdr, 416 (UINT8*) &FvBlob 417 ); 418 419 // 420 // Add new FV into the measured FV list. 421 // 422 ASSERT (mMeasuredBaseFvIndex < PcdGet32 (PcdPeiCoreMaxFvSupported)); 423 if (mMeasuredBaseFvIndex < PcdGet32 (PcdPeiCoreMaxFvSupported)) { 424 mMeasuredBaseFvInfo[mMeasuredBaseFvIndex].BlobBase = FvBase; 425 mMeasuredBaseFvInfo[mMeasuredBaseFvIndex].BlobLength = FvLength; 426 mMeasuredBaseFvIndex++; 427 } 428 429 return Status; 430} 431 432/** 433 Measure main BIOS. 434 435 @param[in] PeiServices Describes the list of possible PEI Services. 436 437 @retval EFI_SUCCESS Operation completed successfully. 438 @retval EFI_OUT_OF_RESOURCES No enough memory to log the new event. 439 @retval EFI_DEVICE_ERROR The command was unsuccessful. 440 441**/ 442EFI_STATUS 443EFIAPI 444MeasureMainBios ( 445 IN EFI_PEI_SERVICES **PeiServices 446 ) 447{ 448 EFI_STATUS Status; 449 UINT32 FvInstances; 450 EFI_PEI_FV_HANDLE VolumeHandle; 451 EFI_FV_INFO VolumeInfo; 452 EFI_PEI_FIRMWARE_VOLUME_PPI *FvPpi; 453 454 FvInstances = 0; 455 while (TRUE) { 456 // 457 // Traverse all firmware volume instances of Static Core Root of Trust for Measurement 458 // (S-CRTM), this firmware volume measure policy can be modified/enhanced by special 459 // platform for special CRTM TPM measuring. 460 // 461 Status = PeiServicesFfsFindNextVolume (FvInstances, &VolumeHandle); 462 if (EFI_ERROR (Status)) { 463 break; 464 } 465 466 // 467 // Measure and record the firmware volume that is dispatched by PeiCore 468 // 469 Status = PeiServicesFfsGetVolumeInfo (VolumeHandle, &VolumeInfo); 470 ASSERT_EFI_ERROR (Status); 471 // 472 // Locate the corresponding FV_PPI according to founded FV's format guid 473 // 474 Status = PeiServicesLocatePpi ( 475 &VolumeInfo.FvFormat, 476 0, 477 NULL, 478 (VOID**)&FvPpi 479 ); 480 if (!EFI_ERROR (Status)) { 481 MeasureFvImage ((EFI_PHYSICAL_ADDRESS) (UINTN) VolumeInfo.FvStart, VolumeInfo.FvSize); 482 } 483 484 FvInstances++; 485 } 486 487 return EFI_SUCCESS; 488} 489 490/** 491 Measure and record the Firmware Volum Information once FvInfoPPI install. 492 493 @param[in] PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation. 494 @param[in] NotifyDescriptor Address of the notification descriptor data structure. 495 @param[in] Ppi Address of the PPI that was installed. 496 497 @retval EFI_SUCCESS The FV Info is measured and recorded to TPM. 498 @return Others Fail to measure FV. 499 500**/ 501EFI_STATUS 502EFIAPI 503FirmwareVolmeInfoPpiNotifyCallback ( 504 IN EFI_PEI_SERVICES **PeiServices, 505 IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor, 506 IN VOID *Ppi 507 ) 508{ 509 EFI_PEI_FIRMWARE_VOLUME_INFO_PPI *Fv; 510 EFI_STATUS Status; 511 EFI_PEI_FIRMWARE_VOLUME_PPI *FvPpi; 512 UINTN Index; 513 514 Fv = (EFI_PEI_FIRMWARE_VOLUME_INFO_PPI *) Ppi; 515 516 // 517 // The PEI Core can not dispatch or load files from memory mapped FVs that do not support FvPpi. 518 // 519 Status = PeiServicesLocatePpi ( 520 &Fv->FvFormat, 521 0, 522 NULL, 523 (VOID**)&FvPpi 524 ); 525 if (EFI_ERROR (Status)) { 526 return EFI_SUCCESS; 527 } 528 529 // 530 // This is an FV from an FFS file, and the parent FV must have already been measured, 531 // No need to measure twice, so just record the FV and return 532 // 533 if (Fv->ParentFvName != NULL || Fv->ParentFileName != NULL ) { 534 535 ASSERT (mMeasuredChildFvIndex < PcdGet32 (PcdPeiCoreMaxFvSupported)); 536 if (mMeasuredChildFvIndex < PcdGet32 (PcdPeiCoreMaxFvSupported)) { 537 // 538 // Check whether FV is in the measured child FV list. 539 // 540 for (Index = 0; Index < mMeasuredChildFvIndex; Index++) { 541 if (mMeasuredChildFvInfo[Index].BlobBase == (EFI_PHYSICAL_ADDRESS) (UINTN) Fv->FvInfo) { 542 return EFI_SUCCESS; 543 } 544 } 545 mMeasuredChildFvInfo[mMeasuredChildFvIndex].BlobBase = (EFI_PHYSICAL_ADDRESS) (UINTN) Fv->FvInfo; 546 mMeasuredChildFvInfo[mMeasuredChildFvIndex].BlobLength = Fv->FvInfoSize; 547 mMeasuredChildFvIndex++; 548 } 549 return EFI_SUCCESS; 550 } 551 552 return MeasureFvImage ((EFI_PHYSICAL_ADDRESS) (UINTN) Fv->FvInfo, Fv->FvInfoSize); 553} 554 555/** 556 Set physicalPresenceLifetimeLock, physicalPresenceHWEnable and physicalPresenceCMDEnable bit by corresponding PCDs. 557 And lock physical presence if needed. 558 559 @param[in] PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation 560 @param[in] NotifyDescriptor Address of the notification descriptor data structure. 561 @param[in] Ppi Address of the PPI that was installed. 562 563 @retval EFI_SUCCESS Operation completed successfully. 564 @retval EFI_ABORTED physicalPresenceCMDEnable is locked. 565 @retval EFI_DEVICE_ERROR The command was unsuccessful. 566 567**/ 568EFI_STATUS 569EFIAPI 570PhysicalPresencePpiNotifyCallback ( 571 IN EFI_PEI_SERVICES **PeiServices, 572 IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor, 573 IN VOID *Ppi 574 ) 575{ 576 EFI_STATUS Status; 577 TPM_PERMANENT_FLAGS TpmPermanentFlags; 578 PEI_LOCK_PHYSICAL_PRESENCE_PPI *LockPhysicalPresencePpi; 579 TPM_PHYSICAL_PRESENCE PhysicalPresenceValue; 580 581 Status = Tpm12GetCapabilityFlagPermanent (&TpmPermanentFlags); 582 if (EFI_ERROR (Status)) { 583 return Status; 584 } 585 586 // 587 // 1. Set physicalPresenceLifetimeLock, physicalPresenceHWEnable and physicalPresenceCMDEnable bit by PCDs. 588 // 589 if (PcdGetBool (PcdPhysicalPresenceLifetimeLock) && !TpmPermanentFlags.physicalPresenceLifetimeLock) { 590 // 591 // Lock TPM LifetimeLock is required, and LifetimeLock is not locked yet. 592 // 593 PhysicalPresenceValue = TPM_PHYSICAL_PRESENCE_LIFETIME_LOCK; 594 595 if (PcdGetBool (PcdPhysicalPresenceCmdEnable)) { 596 PhysicalPresenceValue |= TPM_PHYSICAL_PRESENCE_CMD_ENABLE; 597 TpmPermanentFlags.physicalPresenceCMDEnable = TRUE; 598 } else { 599 PhysicalPresenceValue |= TPM_PHYSICAL_PRESENCE_CMD_DISABLE; 600 TpmPermanentFlags.physicalPresenceCMDEnable = FALSE; 601 } 602 603 if (PcdGetBool (PcdPhysicalPresenceHwEnable)) { 604 PhysicalPresenceValue |= TPM_PHYSICAL_PRESENCE_HW_ENABLE; 605 } else { 606 PhysicalPresenceValue |= TPM_PHYSICAL_PRESENCE_HW_DISABLE; 607 } 608 609 Status = Tpm12PhysicalPresence ( 610 PhysicalPresenceValue 611 ); 612 if (EFI_ERROR (Status)) { 613 return Status; 614 } 615 } 616 617 // 618 // 2. Lock physical presence if it is required. 619 // 620 LockPhysicalPresencePpi = (PEI_LOCK_PHYSICAL_PRESENCE_PPI *) Ppi; 621 if (!LockPhysicalPresencePpi->LockPhysicalPresence ((CONST EFI_PEI_SERVICES**) PeiServices)) { 622 return EFI_SUCCESS; 623 } 624 625 if (!TpmPermanentFlags.physicalPresenceCMDEnable) { 626 if (TpmPermanentFlags.physicalPresenceLifetimeLock) { 627 // 628 // physicalPresenceCMDEnable is locked, can't change. 629 // 630 return EFI_ABORTED; 631 } 632 633 // 634 // Enable physical presence command 635 // It is necessary in order to lock physical presence 636 // 637 Status = Tpm12PhysicalPresence ( 638 TPM_PHYSICAL_PRESENCE_CMD_ENABLE 639 ); 640 if (EFI_ERROR (Status)) { 641 return Status; 642 } 643 } 644 645 // 646 // Lock physical presence 647 // 648 Status = Tpm12PhysicalPresence ( 649 TPM_PHYSICAL_PRESENCE_LOCK 650 ); 651 return Status; 652} 653 654/** 655 Check if TPM chip is activeated or not. 656 657 @param[in] PeiServices Describes the list of possible PEI Services. 658 659 @retval TRUE TPM is activated. 660 @retval FALSE TPM is deactivated. 661 662**/ 663BOOLEAN 664IsTpmUsable ( 665 VOID 666 ) 667{ 668 EFI_STATUS Status; 669 TPM_PERMANENT_FLAGS TpmPermanentFlags; 670 671 Status = Tpm12GetCapabilityFlagPermanent (&TpmPermanentFlags); 672 if (EFI_ERROR (Status)) { 673 return FALSE; 674 } 675 return (BOOLEAN)(!TpmPermanentFlags.deactivated); 676} 677 678/** 679 Do measurement after memory is ready. 680 681 @param[in] PeiServices Describes the list of possible PEI Services. 682 683 @retval EFI_SUCCESS Operation completed successfully. 684 @retval EFI_OUT_OF_RESOURCES No enough memory to log the new event. 685 @retval EFI_DEVICE_ERROR The command was unsuccessful. 686 687**/ 688EFI_STATUS 689EFIAPI 690PeimEntryMP ( 691 IN EFI_PEI_SERVICES **PeiServices 692 ) 693{ 694 EFI_STATUS Status; 695 696 Status = PeiServicesLocatePpi ( 697 &gEfiPeiFirmwareVolumeInfoMeasurementExcludedPpiGuid, 698 0, 699 NULL, 700 (VOID**)&mMeasurementExcludedFvPpi 701 ); 702 // Do not check status, because it is optional 703 704 mMeasuredBaseFvInfo = (EFI_PLATFORM_FIRMWARE_BLOB *) AllocateZeroPool (sizeof (EFI_PLATFORM_FIRMWARE_BLOB) * PcdGet32 (PcdPeiCoreMaxFvSupported)); 705 ASSERT (mMeasuredBaseFvInfo != NULL); 706 mMeasuredChildFvInfo = (EFI_PLATFORM_FIRMWARE_BLOB *) AllocateZeroPool (sizeof (EFI_PLATFORM_FIRMWARE_BLOB) * PcdGet32 (PcdPeiCoreMaxFvSupported)); 707 ASSERT (mMeasuredChildFvInfo != NULL); 708 709 Status = Tpm12RequestUseTpm (); 710 if (EFI_ERROR (Status)) { 711 return Status; 712 } 713 714 if (IsTpmUsable ()) { 715 if (PcdGet8 (PcdTpmScrtmPolicy) == 1) { 716 Status = MeasureCRTMVersion (PeiServices); 717 } 718 719 Status = MeasureMainBios (PeiServices); 720 } 721 722 // 723 // Post callbacks: 724 // 1). for the FvInfoPpi services to measure and record 725 // the additional Fvs to TPM 726 // 2). for the OperatorPresencePpi service to determine whether to 727 // lock the TPM 728 // 729 Status = PeiServicesNotifyPpi (&mNotifyList[0]); 730 ASSERT_EFI_ERROR (Status); 731 732 return Status; 733} 734 735/** 736 Entry point of this module. 737 738 @param[in] FileHandle Handle of the file being invoked. 739 @param[in] PeiServices Describes the list of possible PEI Services. 740 741 @return Status. 742 743**/ 744EFI_STATUS 745EFIAPI 746PeimEntryMA ( 747 IN EFI_PEI_FILE_HANDLE FileHandle, 748 IN CONST EFI_PEI_SERVICES **PeiServices 749 ) 750{ 751 EFI_STATUS Status; 752 EFI_STATUS Status2; 753 EFI_BOOT_MODE BootMode; 754 755 if (!CompareGuid (PcdGetPtr(PcdTpmInstanceGuid), &gEfiTpmDeviceInstanceTpm12Guid)){ 756 DEBUG ((EFI_D_ERROR, "No TPM12 instance required!\n")); 757 return EFI_UNSUPPORTED; 758 } 759 760 if (GetFirstGuidHob (&gTpmErrorHobGuid) != NULL) { 761 DEBUG ((EFI_D_ERROR, "TPM error!\n")); 762 return EFI_DEVICE_ERROR; 763 } 764 765 // 766 // Initialize TPM device 767 // 768 Status = PeiServicesGetBootMode (&BootMode); 769 ASSERT_EFI_ERROR (Status); 770 771 // 772 // In S3 path, skip shadow logic. no measurement is required 773 // 774 if (BootMode != BOOT_ON_S3_RESUME) { 775 Status = (**PeiServices).RegisterForShadow(FileHandle); 776 if (Status == EFI_ALREADY_STARTED) { 777 mImageInMemory = TRUE; 778 } else if (Status == EFI_NOT_FOUND) { 779 ASSERT_EFI_ERROR (Status); 780 } 781 } 782 783 if (!mImageInMemory) { 784 Status = Tpm12RequestUseTpm (); 785 if (EFI_ERROR (Status)) { 786 DEBUG ((DEBUG_ERROR, "TPM not detected!\n")); 787 goto Done; 788 } 789 790 if (PcdGet8 (PcdTpmInitializationPolicy) == 1) { 791 if (BootMode == BOOT_ON_S3_RESUME) { 792 Status = Tpm12Startup (TPM_ST_STATE); 793 } else { 794 Status = Tpm12Startup (TPM_ST_CLEAR); 795 } 796 if (EFI_ERROR (Status) ) { 797 goto Done; 798 } 799 } 800 801 // 802 // TpmSelfTest is optional on S3 path, skip it to save S3 time 803 // 804 if (BootMode != BOOT_ON_S3_RESUME) { 805 Status = Tpm12ContinueSelfTest (); 806 if (EFI_ERROR (Status)) { 807 goto Done; 808 } 809 } 810 811 // 812 // Only intall TpmInitializedPpi on success 813 // 814 Status = PeiServicesInstallPpi (&mTpmInitializedPpiList); 815 ASSERT_EFI_ERROR (Status); 816 } 817 818 if (mImageInMemory) { 819 Status = PeimEntryMP ((EFI_PEI_SERVICES**)PeiServices); 820 return Status; 821 } 822 823Done: 824 if (EFI_ERROR (Status)) { 825 DEBUG ((EFI_D_ERROR, "TPM error! Build Hob\n")); 826 BuildGuidHob (&gTpmErrorHobGuid,0); 827 REPORT_STATUS_CODE ( 828 EFI_ERROR_CODE | EFI_ERROR_MINOR, 829 (PcdGet32 (PcdStatusCodeSubClassTpmDevice) | EFI_P_EC_INTERFACE_ERROR) 830 ); 831 } 832 // 833 // Always intall TpmInitializationDonePpi no matter success or fail. 834 // Other driver can know TPM initialization state by TpmInitializedPpi. 835 // 836 Status2 = PeiServicesInstallPpi (&mTpmInitializationDonePpiList); 837 ASSERT_EFI_ERROR (Status2); 838 839 return Status; 840} 841