]> git.proxmox.com Git - mirror_edk2.git/blame - SecurityPkg/Tcg/TcgPei/TcgPei.c
SecurityPkg/TcgPei: Use updated Tpm12CommandLib APIs
[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
b558f8bc 4Copyright (c) 2005 - 2016, Intel Corporation. All rights reserved.<BR>\r
0c18794e 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
8http://opensource.org/licenses/bsd-license.php\r
9\r
10THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r
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
132 FirmwareVolmeInfoPpiNotifyCallback \r
2aadc920 133 },\r
c7935105
SZ
134 {\r
135 EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK,\r
136 &gEfiPeiFirmwareVolumeInfo2PpiGuid,\r
137 FirmwareVolmeInfoPpiNotifyCallback \r
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
148 Guid Hob payload layout is \r
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
168{ \r
0758c830 169 MEASURED_HOB_DATA *MeasuredHobData;\r
2aadc920 170\r
0758c830 171 MeasuredHobData = NULL;\r
2aadc920 172\r
173 //\r
0758c830 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
241 @param[in] HashData Physical address of the start of the data buffer \r
242 to be hashed, extended, and logged.\r
243 @param[in] HashDataLen The length, in bytes, of the buffer referenced by HashData.\r
0c18794e 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
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
6f785cfc
JY
263 \r
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
352 Measure FV image. \r
353 Add it into the measured FV list after the FV is measured successfully. \r
354\r
355 @param[in] FvBase Base address of FV image.\r
356 @param[in] FvLength Length of FV image.\r
357\r
358 @retval EFI_SUCCESS Fv image is measured successfully \r
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
397 \r
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
453 \r
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
465 \r
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
475 &VolumeInfo.FvFormat, \r
476 0, \r
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
520 &Fv->FvFormat, \r
521 0, \r
522 NULL,\r
523 (VOID**)&FvPpi\r
524 );\r
525 if (EFI_ERROR (Status)) {\r
526 return EFI_SUCCESS;\r
527 }\r
528 \r
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
2aadc920 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
591 // Lock TPM LifetimeLock is required, and LifetimeLock is not locked yet. \r
592 //\r
593 PhysicalPresenceValue = TPM_PHYSICAL_PRESENCE_LIFETIME_LOCK;\r
594\r
595 if (PcdGetBool (PcdPhysicalPresenceCmdEnable)) {\r
596 PhysicalPresenceValue |= TPM_PHYSICAL_PRESENCE_CMD_ENABLE;\r
45500265 597 TpmPermanentFlags.physicalPresenceCMDEnable = TRUE;\r
5a500332 598 } else {\r
599 PhysicalPresenceValue |= TPM_PHYSICAL_PRESENCE_CMD_DISABLE;\r
45500265 600 TpmPermanentFlags.physicalPresenceCMDEnable = FALSE;\r
5a500332 601 }\r
0c18794e 602\r
5a500332 603 if (PcdGetBool (PcdPhysicalPresenceHwEnable)) {\r
604 PhysicalPresenceValue |= TPM_PHYSICAL_PRESENCE_HW_ENABLE;\r
605 } else {\r
606 PhysicalPresenceValue |= TPM_PHYSICAL_PRESENCE_HW_DISABLE;\r
607 } \r
608 \r
45500265 609 Status = Tpm12PhysicalPresence (\r
5a500332 610 PhysicalPresenceValue\r
611 );\r
612 if (EFI_ERROR (Status)) {\r
613 return Status;\r
614 }\r
615 }\r
616 \r
617 //\r
618 // 2. Lock physical presence if it is required.\r
619 //\r
620 LockPhysicalPresencePpi = (PEI_LOCK_PHYSICAL_PRESENCE_PPI *) Ppi;\r
621 if (!LockPhysicalPresencePpi->LockPhysicalPresence ((CONST EFI_PEI_SERVICES**) PeiServices)) {\r
622 return EFI_SUCCESS;\r
0c18794e 623 }\r
624\r
45500265
MK
625 if (!TpmPermanentFlags.physicalPresenceCMDEnable) {\r
626 if (TpmPermanentFlags.physicalPresenceLifetimeLock) {\r
0c18794e 627 //\r
628 // physicalPresenceCMDEnable is locked, can't change.\r
629 //\r
630 return EFI_ABORTED;\r
631 }\r
632\r
633 //\r
634 // Enable physical presence command\r
635 // It is necessary in order to lock physical presence\r
636 //\r
45500265 637 Status = Tpm12PhysicalPresence (\r
0c18794e 638 TPM_PHYSICAL_PRESENCE_CMD_ENABLE\r
639 );\r
640 if (EFI_ERROR (Status)) {\r
641 return Status;\r
642 }\r
643 }\r
644\r
645 //\r
646 // Lock physical presence\r
647 // \r
45500265 648 Status = Tpm12PhysicalPresence (\r
0c18794e 649 TPM_PHYSICAL_PRESENCE_LOCK\r
650 );\r
651 return Status;\r
652}\r
653\r
654/**\r
655 Check if TPM chip is activeated or not.\r
656\r
657 @param[in] PeiServices Describes the list of possible PEI Services.\r
0c18794e 658\r
659 @retval TRUE TPM is activated.\r
660 @retval FALSE TPM is deactivated.\r
661\r
662**/\r
663BOOLEAN\r
0c18794e 664IsTpmUsable (\r
45500265 665 VOID\r
0c18794e 666 )\r
667{\r
45500265
MK
668 EFI_STATUS Status;\r
669 TPM_PERMANENT_FLAGS TpmPermanentFlags;\r
0c18794e 670\r
45500265 671 Status = Tpm12GetCapabilityFlagPermanent (&TpmPermanentFlags);\r
0c18794e 672 if (EFI_ERROR (Status)) {\r
673 return FALSE;\r
674 }\r
45500265 675 return (BOOLEAN)(!TpmPermanentFlags.deactivated);\r
0c18794e 676}\r
677\r
678/**\r
679 Do measurement after memory is ready.\r
680\r
681 @param[in] PeiServices Describes the list of possible PEI Services.\r
682\r
683 @retval EFI_SUCCESS Operation completed successfully.\r
684 @retval EFI_OUT_OF_RESOURCES No enough memory to log the new event.\r
685 @retval EFI_DEVICE_ERROR The command was unsuccessful.\r
686\r
687**/\r
688EFI_STATUS\r
689EFIAPI\r
690PeimEntryMP (\r
691 IN EFI_PEI_SERVICES **PeiServices\r
692 )\r
693{\r
694 EFI_STATUS Status;\r
0c18794e 695\r
c1d93242
JY
696 Status = PeiServicesLocatePpi (\r
697 &gEfiPeiFirmwareVolumeInfoMeasurementExcludedPpiGuid, \r
698 0, \r
699 NULL,\r
700 (VOID**)&mMeasurementExcludedFvPpi\r
701 );\r
702 // Do not check status, because it is optional\r
703\r
b5412eac
DG
704 mMeasuredBaseFvInfo = (EFI_PLATFORM_FIRMWARE_BLOB *) AllocateZeroPool (sizeof (EFI_PLATFORM_FIRMWARE_BLOB) * PcdGet32 (PcdPeiCoreMaxFvSupported));\r
705 ASSERT (mMeasuredBaseFvInfo != NULL);\r
706 mMeasuredChildFvInfo = (EFI_PLATFORM_FIRMWARE_BLOB *) AllocateZeroPool (sizeof (EFI_PLATFORM_FIRMWARE_BLOB) * PcdGet32 (PcdPeiCoreMaxFvSupported));\r
707 ASSERT (mMeasuredChildFvInfo != NULL);\r
708\r
b558f8bc 709 Status = Tpm12RequestUseTpm ();\r
0c18794e 710 if (EFI_ERROR (Status)) {\r
711 return Status;\r
712 }\r
713\r
45500265 714 if (IsTpmUsable ()) {\r
c1d93242 715 if (PcdGet8 (PcdTpmScrtmPolicy) == 1) {\r
b558f8bc 716 Status = MeasureCRTMVersion (PeiServices);\r
c1d93242 717 }\r
0c18794e 718\r
b558f8bc 719 Status = MeasureMainBios (PeiServices);\r
0c18794e 720 } \r
721\r
722 //\r
723 // Post callbacks:\r
724 // 1). for the FvInfoPpi services to measure and record\r
725 // the additional Fvs to TPM\r
726 // 2). for the OperatorPresencePpi service to determine whether to \r
727 // lock the TPM\r
728 //\r
729 Status = PeiServicesNotifyPpi (&mNotifyList[0]);\r
730 ASSERT_EFI_ERROR (Status);\r
731\r
732 return Status;\r
733}\r
734\r
735/**\r
736 Entry point of this module.\r
737\r
738 @param[in] FileHandle Handle of the file being invoked.\r
739 @param[in] PeiServices Describes the list of possible PEI Services.\r
740\r
741 @return Status.\r
742\r
743**/\r
744EFI_STATUS\r
745EFIAPI\r
746PeimEntryMA (\r
747 IN EFI_PEI_FILE_HANDLE FileHandle,\r
748 IN CONST EFI_PEI_SERVICES **PeiServices\r
749 )\r
750{\r
751 EFI_STATUS Status;\r
83a276f6 752 EFI_STATUS Status2;\r
0c18794e 753 EFI_BOOT_MODE BootMode;\r
0c18794e 754\r
c1d93242
JY
755 if (!CompareGuid (PcdGetPtr(PcdTpmInstanceGuid), &gEfiTpmDeviceInstanceTpm12Guid)){\r
756 DEBUG ((EFI_D_ERROR, "No TPM12 instance required!\n"));\r
757 return EFI_UNSUPPORTED;\r
758 }\r
759\r
3dd05ac3
JY
760 if (GetFirstGuidHob (&gTpmErrorHobGuid) != NULL) {\r
761 DEBUG ((EFI_D_ERROR, "TPM error!\n"));\r
762 return EFI_DEVICE_ERROR;\r
763 }\r
764\r
055c829c 765 //\r
766 // Initialize TPM device\r
767 //\r
768 Status = PeiServicesGetBootMode (&BootMode);\r
769 ASSERT_EFI_ERROR (Status);\r
770\r
771 //\r
772 // In S3 path, skip shadow logic. no measurement is required\r
773 //\r
774 if (BootMode != BOOT_ON_S3_RESUME) {\r
775 Status = (**PeiServices).RegisterForShadow(FileHandle);\r
776 if (Status == EFI_ALREADY_STARTED) {\r
777 mImageInMemory = TRUE;\r
778 } else if (Status == EFI_NOT_FOUND) {\r
779 ASSERT_EFI_ERROR (Status);\r
780 }\r
0c18794e 781 }\r
782\r
783 if (!mImageInMemory) {\r
b558f8bc 784 Status = Tpm12RequestUseTpm ();\r
0c18794e 785 if (EFI_ERROR (Status)) {\r
786 DEBUG ((DEBUG_ERROR, "TPM not detected!\n"));\r
83a276f6 787 goto Done;\r
0c18794e 788 }\r
789\r
c1d93242 790 if (PcdGet8 (PcdTpmInitializationPolicy) == 1) {\r
45500265
MK
791 if (BootMode == BOOT_ON_S3_RESUME) {\r
792 Status = Tpm12Startup (TPM_ST_STATE);\r
793 } else {\r
794 Status = Tpm12Startup (TPM_ST_CLEAR);\r
795 }\r
c1d93242 796 if (EFI_ERROR (Status) ) {\r
83a276f6 797 goto Done;\r
c1d93242 798 }\r
0c18794e 799 }\r
6f6c7857 800\r
801 //\r
802 // TpmSelfTest is optional on S3 path, skip it to save S3 time\r
803 //\r
804 if (BootMode != BOOT_ON_S3_RESUME) {\r
45500265 805 Status = Tpm12ContinueSelfTest ();\r
6f6c7857 806 if (EFI_ERROR (Status)) {\r
83a276f6 807 goto Done;\r
6f6c7857 808 }\r
0c18794e 809 }\r
6f6c7857 810\r
83a276f6
JY
811 //\r
812 // Only intall TpmInitializedPpi on success\r
813 //\r
0c18794e 814 Status = PeiServicesInstallPpi (&mTpmInitializedPpiList);\r
815 ASSERT_EFI_ERROR (Status);\r
816 }\r
817\r
818 if (mImageInMemory) {\r
819 Status = PeimEntryMP ((EFI_PEI_SERVICES**)PeiServices);\r
83a276f6 820 return Status;\r
0c18794e 821 }\r
822\r
83a276f6 823Done:\r
3dd05ac3
JY
824 if (EFI_ERROR (Status)) {\r
825 DEBUG ((EFI_D_ERROR, "TPM error! Build Hob\n"));\r
826 BuildGuidHob (&gTpmErrorHobGuid,0);\r
827 REPORT_STATUS_CODE (\r
828 EFI_ERROR_CODE | EFI_ERROR_MINOR,\r
829 (PcdGet32 (PcdStatusCodeSubClassTpmDevice) | EFI_P_EC_INTERFACE_ERROR)\r
830 );\r
831 }\r
83a276f6
JY
832 //\r
833 // Always intall TpmInitializationDonePpi no matter success or fail.\r
834 // Other driver can know TPM initialization state by TpmInitializedPpi.\r
835 //\r
836 Status2 = PeiServicesInstallPpi (&mTpmInitializationDonePpiList);\r
837 ASSERT_EFI_ERROR (Status2);\r
838\r
0c18794e 839 return Status;\r
840}\r