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