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
EndofPeiSignalNotifyCallBack(IN EFI_PEI_SERVICES ** PeiServices,IN EFI_PEI_NOTIFY_DESCRIPTOR * NotifyDescriptor,IN VOID * Ppi)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
TpmCommHashAll(IN CONST UINT8 * Data,IN UINTN DataLen,OUT TPM_DIGEST * Digest)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
HashLogExtendEvent(IN EFI_PEI_SERVICES ** PeiServices,IN UINT8 * HashData,IN UINTN HashDataLen,IN TCG_PCR_EVENT_HDR * NewEventHdr,IN UINT8 * NewEventData)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
MeasureCRTMVersion(IN EFI_PEI_SERVICES ** PeiServices)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
MeasureFvImage(IN EFI_PHYSICAL_ADDRESS FvBase,IN UINT64 FvLength)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
MeasureMainBios(IN EFI_PEI_SERVICES ** PeiServices)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
FirmwareVolmeInfoPpiNotifyCallback(IN EFI_PEI_SERVICES ** PeiServices,IN EFI_PEI_NOTIFY_DESCRIPTOR * NotifyDescriptor,IN VOID * Ppi)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
PhysicalPresencePpiNotifyCallback(IN EFI_PEI_SERVICES ** PeiServices,IN EFI_PEI_NOTIFY_DESCRIPTOR * NotifyDescriptor,IN VOID * Ppi)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
IsTpmUsable(VOID)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
PeimEntryMP(IN EFI_PEI_SERVICES ** PeiServices)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
PeimEntryMA(IN EFI_PEI_FILE_HANDLE FileHandle,IN CONST EFI_PEI_SERVICES ** PeiServices)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