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