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