1 /** @file 2 Initialize TPM device and measure FVs before handing off control to DXE. 3 4 Copyright (c) 2005 - 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 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 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 Single function calculates SHA1 digest value for all raw data. It 203 combines 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 **/ 211 EFI_STATUS 212 EFIAPI 213 TpmCommHashAll ( 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 **/ 252 EFI_STATUS 253 HashLogExtendEvent ( 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 302 Done: 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 **/ 325 EFI_STATUS 326 EFIAPI 327 MeasureCRTMVersion ( 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 **/ 364 EFI_STATUS 365 EFIAPI 366 MeasureFvImage ( 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 **/ 442 EFI_STATUS 443 EFIAPI 444 MeasureMainBios ( 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 **/ 501 EFI_STATUS 502 EFIAPI 503 FirmwareVolmeInfoPpiNotifyCallback ( 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 **/ 568 EFI_STATUS 569 EFIAPI 570 PhysicalPresencePpiNotifyCallback ( 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 **/ 663 BOOLEAN 664 IsTpmUsable ( 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 **/ 688 EFI_STATUS 689 EFIAPI 690 PeimEntryMP ( 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 **/ 744 EFI_STATUS 745 EFIAPI 746 PeimEntryMA ( 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 823 Done: 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