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