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