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