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