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