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