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