]> git.proxmox.com Git - mirror_edk2.git/blame - SecurityPkg/Tcg/TcgPei/TcgPei.c
SecurityPkg: Change use of EFI_D_* to DEBUG_*
[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
3e07c656 4Copyright (c) 2005 - 2020, Intel Corporation. All rights reserved.<BR>\r
289b714b 5SPDX-License-Identifier: BSD-2-Clause-Patent\r
0c18794e 6\r
7**/\r
8\r
9#include <PiPei.h>\r
10\r
11#include <IndustryStandard/Tpm12.h>\r
12#include <IndustryStandard/UefiTcgPlatform.h>\r
13#include <Ppi/FirmwareVolumeInfo.h>\r
c7935105 14#include <Ppi/FirmwareVolumeInfo2.h>\r
0c18794e 15#include <Ppi/LockPhysicalPresence.h>\r
16#include <Ppi/TpmInitialized.h>\r
17#include <Ppi/FirmwareVolume.h>\r
2aadc920 18#include <Ppi/EndOfPeiPhase.h>\r
c1d93242 19#include <Ppi/FirmwareVolumeInfoMeasurementExcluded.h>\r
3e07c656 20#include <Ppi/Tcg.h>\r
2aadc920 21\r
0c18794e 22#include <Guid/TcgEventHob.h>\r
0758c830 23#include <Guid/MeasuredFvHob.h>\r
c1d93242 24#include <Guid/TpmInstance.h>\r
ffde2246 25#include <Guid/MigratedFvInfo.h>\r
2aadc920 26\r
0c18794e 27#include <Library/DebugLib.h>\r
28#include <Library/BaseMemoryLib.h>\r
29#include <Library/PeiServicesLib.h>\r
30#include <Library/PeimEntryPoint.h>\r
0c18794e 31#include <Library/HobLib.h>\r
32#include <Library/PcdLib.h>\r
33#include <Library/PeiServicesTablePointerLib.h>\r
333a53ee 34#include <Library/BaseLib.h>\r
b5412eac 35#include <Library/MemoryAllocationLib.h>\r
6f785cfc 36#include <Library/ReportStatusCodeLib.h>\r
45500265
MK
37#include <Library/Tpm12DeviceLib.h>\r
38#include <Library/Tpm12CommandLib.h>\r
39#include <Library/BaseCryptLib.h>\r
d9c5beb1 40#include <Library/PerformanceLib.h>\r
0c18794e 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
83a276f6
JY
50EFI_PEI_PPI_DESCRIPTOR mTpmInitializationDonePpiList = {\r
51 EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST,\r
52 &gPeiTpmInitializationDonePpiGuid,\r
53 NULL\r
54};\r
55\r
3e07c656
JY
56/**\r
57 Do a hash operation on a data buffer, extend a specific TPM PCR with the hash result,\r
58 and build a GUIDed HOB recording the event which will be passed to the DXE phase and\r
59 added into the Event Log.\r
60\r
61 @param[in] This Indicates the calling context\r
62 @param[in] Flags Bitmap providing additional information.\r
63 @param[in] HashData Physical address of the start of the data buffer\r
64 to be hashed, extended, and logged.\r
65 @param[in] HashDataLen The length, in bytes, of the buffer referenced by HashData.\r
66 @param[in] NewEventHdr Pointer to a TCG_PCR_EVENT_HDR data structure.\r
67 @param[in] NewEventData Pointer to the new event data.\r
68\r
69 @retval EFI_SUCCESS Operation completed successfully.\r
70 @retval EFI_OUT_OF_RESOURCES No enough memory to log the new event.\r
71 @retval EFI_DEVICE_ERROR The command was unsuccessful.\r
72\r
73**/\r
74EFI_STATUS\r
75EFIAPI\r
76HashLogExtendEvent (\r
77 IN EDKII_TCG_PPI *This,\r
78 IN UINT64 Flags,\r
79 IN UINT8 *HashData,\r
80 IN UINTN HashDataLen,\r
81 IN TCG_PCR_EVENT_HDR *NewEventHdr,\r
82 IN UINT8 *NewEventData\r
83 );\r
84\r
85EDKII_TCG_PPI mEdkiiTcgPpi = {\r
86 HashLogExtendEvent\r
87};\r
88\r
89EFI_PEI_PPI_DESCRIPTOR mTcgPpiList = {\r
90 EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST,\r
91 &gEdkiiTcgPpiGuid,\r
92 &mEdkiiTcgPpi\r
93};\r
94\r
aa8c6e2a
SZ
95//\r
96// Number of firmware blobs to grow by each time we run out of room\r
97//\r
98#define FIRMWARE_BLOB_GROWTH_STEP 4\r
99\r
b5412eac 100EFI_PLATFORM_FIRMWARE_BLOB *mMeasuredBaseFvInfo;\r
aa8c6e2a 101UINT32 mMeasuredMaxBaseFvIndex = 0;\r
2aadc920 102UINT32 mMeasuredBaseFvIndex = 0;\r
103\r
b5412eac 104EFI_PLATFORM_FIRMWARE_BLOB *mMeasuredChildFvInfo;\r
aa8c6e2a 105UINT32 mMeasuredMaxChildFvIndex = 0;\r
2aadc920 106UINT32 mMeasuredChildFvIndex = 0;\r
107\r
c1d93242
JY
108EFI_PEI_FIRMWARE_VOLUME_INFO_MEASUREMENT_EXCLUDED_PPI *mMeasurementExcludedFvPpi;\r
109\r
0c18794e 110/**\r
111 Lock physical presence if needed.\r
112\r
113 @param[in] PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation\r
114 @param[in] NotifyDescriptor Address of the notification descriptor data structure.\r
115 @param[in] Ppi Address of the PPI that was installed.\r
116\r
117 @retval EFI_SUCCESS Operation completed successfully.\r
118\r
119**/\r
120EFI_STATUS\r
121EFIAPI\r
122PhysicalPresencePpiNotifyCallback (\r
123 IN EFI_PEI_SERVICES **PeiServices,\r
124 IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor,\r
125 IN VOID *Ppi\r
126 );\r
127\r
128/**\r
d6b926e7 129 Measure and record the Firmware Volume Information once FvInfoPPI install.\r
0c18794e 130\r
131 @param[in] PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.\r
132 @param[in] NotifyDescriptor Address of the notification descriptor data structure.\r
133 @param[in] Ppi Address of the PPI that was installed.\r
134\r
135 @retval EFI_SUCCESS The FV Info is measured and recorded to TPM.\r
136 @return Others Fail to measure FV.\r
137\r
138**/\r
139EFI_STATUS\r
140EFIAPI\r
d6b926e7 141FirmwareVolumeInfoPpiNotifyCallback (\r
0c18794e 142 IN EFI_PEI_SERVICES **PeiServices,\r
143 IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor,\r
144 IN VOID *Ppi\r
145 );\r
146\r
2aadc920 147/**\r
d6b926e7 148 Record all measured Firmware Volume Information into a Guid Hob\r
2aadc920 149\r
150 @param[in] PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.\r
151 @param[in] NotifyDescriptor Address of the notification descriptor data structure.\r
152 @param[in] Ppi Address of the PPI that was installed.\r
153\r
154 @retval EFI_SUCCESS The FV Info is measured and recorded to TPM.\r
155 @return Others Fail to measure FV.\r
156\r
157**/\r
158EFI_STATUS\r
159EFIAPI\r
160EndofPeiSignalNotifyCallBack (\r
161 IN EFI_PEI_SERVICES **PeiServices,\r
162 IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor,\r
163 IN VOID *Ppi\r
164 );\r
165\r
0c18794e 166EFI_PEI_NOTIFY_DESCRIPTOR mNotifyList[] = {\r
167 {\r
168 EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK,\r
169 &gPeiLockPhysicalPresencePpiGuid,\r
170 PhysicalPresencePpiNotifyCallback\r
171 },\r
172 {\r
2aadc920 173 EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK,\r
0c18794e 174 &gEfiPeiFirmwareVolumeInfoPpiGuid,\r
d6b926e7 175 FirmwareVolumeInfoPpiNotifyCallback\r
2aadc920 176 },\r
c7935105
SZ
177 {\r
178 EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK,\r
179 &gEfiPeiFirmwareVolumeInfo2PpiGuid,\r
d6b926e7 180 FirmwareVolumeInfoPpiNotifyCallback\r
c7935105 181 },\r
2aadc920 182 {\r
183 (EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),\r
184 &gEfiEndOfPeiSignalPpiGuid,\r
185 EndofPeiSignalNotifyCallBack\r
0c18794e 186 }\r
187};\r
188\r
2aadc920 189/**\r
dd40a1f8 190 Record all measured Firmware Volume Information into a Guid Hob\r
b3548d32 191 Guid Hob payload layout is\r
2aadc920 192\r
193 UINT32 *************************** FIRMWARE_BLOB number\r
194 EFI_PLATFORM_FIRMWARE_BLOB******** BLOB Array\r
195\r
196 @param[in] PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.\r
197 @param[in] NotifyDescriptor Address of the notification descriptor data structure.\r
198 @param[in] Ppi Address of the PPI that was installed.\r
199\r
200 @retval EFI_SUCCESS The FV Info is measured and recorded to TPM.\r
201 @return Others Fail to measure FV.\r
202\r
203**/\r
204EFI_STATUS\r
205EFIAPI\r
206EndofPeiSignalNotifyCallBack (\r
207 IN EFI_PEI_SERVICES **PeiServices,\r
208 IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor,\r
209 IN VOID *Ppi\r
210 )\r
b3548d32 211{\r
0758c830 212 MEASURED_HOB_DATA *MeasuredHobData;\r
2aadc920 213\r
0758c830 214 MeasuredHobData = NULL;\r
2aadc920 215\r
d9c5beb1
DB
216 PERF_CALLBACK_BEGIN (&gEfiEndOfPeiSignalPpiGuid);\r
217\r
2aadc920 218 //\r
b3548d32 219 // Create a Guid hob to save all measured Fv\r
2aadc920 220 //\r
0758c830 221 MeasuredHobData = BuildGuidHob(\r
222 &gMeasuredFvHobGuid,\r
223 sizeof(UINTN) + sizeof(EFI_PLATFORM_FIRMWARE_BLOB) * (mMeasuredBaseFvIndex + mMeasuredChildFvIndex)\r
224 );\r
2aadc920 225\r
0758c830 226 if (MeasuredHobData != NULL){\r
2aadc920 227 //\r
228 // Save measured FV info enty number\r
229 //\r
0758c830 230 MeasuredHobData->Num = mMeasuredBaseFvIndex + mMeasuredChildFvIndex;\r
2aadc920 231\r
2aadc920 232 //\r
233 // Save measured base Fv info\r
234 //\r
0758c830 235 CopyMem (MeasuredHobData->MeasuredFvBuf, mMeasuredBaseFvInfo, sizeof(EFI_PLATFORM_FIRMWARE_BLOB) * (mMeasuredBaseFvIndex));\r
2aadc920 236\r
2aadc920 237 //\r
238 // Save measured child Fv info\r
239 //\r
0758c830 240 CopyMem (&MeasuredHobData->MeasuredFvBuf[mMeasuredBaseFvIndex] , mMeasuredChildFvInfo, sizeof(EFI_PLATFORM_FIRMWARE_BLOB) * (mMeasuredChildFvIndex));\r
2aadc920 241 }\r
242\r
d9c5beb1
DB
243 PERF_CALLBACK_END (&gEfiEndOfPeiSignalPpiGuid);\r
244\r
2aadc920 245 return EFI_SUCCESS;\r
246}\r
0c18794e 247\r
45500265
MK
248/**\r
249Single function calculates SHA1 digest value for all raw data. It\r
250combines Sha1Init(), Sha1Update() and Sha1Final().\r
251\r
252@param[in] Data Raw data to be digested.\r
253@param[in] DataLen Size of the raw data.\r
254@param[out] Digest Pointer to a buffer that stores the final digest.\r
255\r
256@retval EFI_SUCCESS Always successfully calculate the final digest.\r
257**/\r
258EFI_STATUS\r
259EFIAPI\r
260TpmCommHashAll (\r
261 IN CONST UINT8 *Data,\r
262 IN UINTN DataLen,\r
263 OUT TPM_DIGEST *Digest\r
264 )\r
265{\r
266 VOID *Sha1Ctx;\r
267 UINTN CtxSize;\r
268\r
269 CtxSize = Sha1GetContextSize ();\r
270 Sha1Ctx = AllocatePool (CtxSize);\r
271 ASSERT (Sha1Ctx != NULL);\r
272\r
273 Sha1Init (Sha1Ctx);\r
274 Sha1Update (Sha1Ctx, Data, DataLen);\r
275 Sha1Final (Sha1Ctx, (UINT8 *)Digest);\r
276\r
277 FreePool (Sha1Ctx);\r
278\r
279 return EFI_SUCCESS;\r
280}\r
281\r
0c18794e 282/**\r
283 Do a hash operation on a data buffer, extend a specific TPM PCR with the hash result,\r
284 and build a GUIDed HOB recording the event which will be passed to the DXE phase and\r
285 added into the Event Log.\r
286\r
3e07c656
JY
287 @param[in] This Indicates the calling context.\r
288 @param[in] Flags Bitmap providing additional information.\r
b3548d32 289 @param[in] HashData Physical address of the start of the data buffer\r
0c18794e 290 to be hashed, extended, and logged.\r
291 @param[in] HashDataLen The length, in bytes, of the buffer referenced by HashData.\r
b3548d32
LG
292 @param[in] NewEventHdr Pointer to a TCG_PCR_EVENT_HDR data structure.\r
293 @param[in] NewEventData Pointer to the new event data.\r
0c18794e 294\r
295 @retval EFI_SUCCESS Operation completed successfully.\r
296 @retval EFI_OUT_OF_RESOURCES No enough memory to log the new event.\r
297 @retval EFI_DEVICE_ERROR The command was unsuccessful.\r
298\r
299**/\r
300EFI_STATUS\r
3e07c656 301EFIAPI\r
0c18794e 302HashLogExtendEvent (\r
3e07c656
JY
303 IN EDKII_TCG_PPI *This,\r
304 IN UINT64 Flags,\r
0c18794e 305 IN UINT8 *HashData,\r
306 IN UINTN HashDataLen,\r
0c18794e 307 IN TCG_PCR_EVENT_HDR *NewEventHdr,\r
308 IN UINT8 *NewEventData\r
309 )\r
310{\r
311 EFI_STATUS Status;\r
312 VOID *HobData;\r
b3548d32 313\r
6f785cfc
JY
314 if (GetFirstGuidHob (&gTpmErrorHobGuid) != NULL) {\r
315 return EFI_DEVICE_ERROR;\r
316 }\r
0c18794e 317\r
318 HobData = NULL;\r
319 if (HashDataLen != 0) {\r
320 Status = TpmCommHashAll (\r
321 HashData,\r
322 HashDataLen,\r
323 &NewEventHdr->Digest\r
324 );\r
6f785cfc
JY
325 if (EFI_ERROR (Status)) {\r
326 goto Done;\r
327 }\r
0c18794e 328 }\r
329\r
45500265 330 Status = Tpm12Extend (\r
0c18794e 331 &NewEventHdr->Digest,\r
332 NewEventHdr->PCRIndex,\r
333 NULL\r
334 );\r
6f785cfc
JY
335 if (EFI_ERROR (Status)) {\r
336 goto Done;\r
337 }\r
0c18794e 338\r
339 HobData = BuildGuidHob (\r
340 &gTcgEventEntryHobGuid,\r
341 sizeof (*NewEventHdr) + NewEventHdr->EventSize\r
342 );\r
343 if (HobData == NULL) {\r
6f785cfc
JY
344 Status = EFI_OUT_OF_RESOURCES;\r
345 goto Done;\r
0c18794e 346 }\r
347\r
348 CopyMem (HobData, NewEventHdr, sizeof (*NewEventHdr));\r
349 HobData = (VOID *) ((UINT8*)HobData + sizeof (*NewEventHdr));\r
350 CopyMem (HobData, NewEventData, NewEventHdr->EventSize);\r
6f785cfc
JY
351\r
352Done:\r
353 if ((Status == EFI_DEVICE_ERROR) || (Status == EFI_TIMEOUT)) {\r
e905fbb0 354 DEBUG ((DEBUG_ERROR, "HashLogExtendEvent - %r. Disable TPM.\n", Status));\r
6f785cfc
JY
355 BuildGuidHob (&gTpmErrorHobGuid,0);\r
356 REPORT_STATUS_CODE (\r
357 EFI_ERROR_CODE | EFI_ERROR_MINOR,\r
358 (PcdGet32 (PcdStatusCodeSubClassTpmDevice) | EFI_P_EC_INTERFACE_ERROR)\r
359 );\r
360 Status = EFI_DEVICE_ERROR;\r
361 }\r
362 return Status;\r
0c18794e 363}\r
364\r
365/**\r
366 Measure CRTM version.\r
367\r
368 @param[in] PeiServices Describes the list of possible PEI Services.\r
0c18794e 369\r
370 @retval EFI_SUCCESS Operation completed successfully.\r
371 @retval EFI_OUT_OF_RESOURCES No enough memory to log the new event.\r
372 @retval EFI_DEVICE_ERROR The command was unsuccessful.\r
373\r
374**/\r
375EFI_STATUS\r
376EFIAPI\r
377MeasureCRTMVersion (\r
b558f8bc 378 IN EFI_PEI_SERVICES **PeiServices\r
0c18794e 379 )\r
380{\r
381 TCG_PCR_EVENT_HDR TcgEventHdr;\r
382\r
383 //\r
333a53ee 384 // Use FirmwareVersion string to represent CRTM version.\r
0c18794e 385 // OEMs should get real CRTM version string and measure it.\r
386 //\r
387\r
388 TcgEventHdr.PCRIndex = 0;\r
389 TcgEventHdr.EventType = EV_S_CRTM_VERSION;\r
8cc06814 390 TcgEventHdr.EventSize = (UINT32) StrSize((CHAR16*)PcdGetPtr (PcdFirmwareVersionString));\r
333a53ee 391\r
0c18794e 392 return HashLogExtendEvent (\r
3e07c656
JY
393 &mEdkiiTcgPpi,\r
394 0,\r
333a53ee 395 (UINT8*)PcdGetPtr (PcdFirmwareVersionString),\r
0c18794e 396 TcgEventHdr.EventSize,\r
0c18794e 397 &TcgEventHdr,\r
333a53ee 398 (UINT8*)PcdGetPtr (PcdFirmwareVersionString)\r
0c18794e 399 );\r
400}\r
401\r
402/**\r
b3548d32
LG
403 Measure FV image.\r
404 Add it into the measured FV list after the FV is measured successfully.\r
0c18794e 405\r
406 @param[in] FvBase Base address of FV image.\r
407 @param[in] FvLength Length of FV image.\r
408\r
b3548d32 409 @retval EFI_SUCCESS Fv image is measured successfully\r
0c18794e 410 or it has been already measured.\r
411 @retval EFI_OUT_OF_RESOURCES No enough memory to log the new event.\r
412 @retval EFI_DEVICE_ERROR The command was unsuccessful.\r
413\r
414**/\r
415EFI_STATUS\r
416EFIAPI\r
417MeasureFvImage (\r
418 IN EFI_PHYSICAL_ADDRESS FvBase,\r
419 IN UINT64 FvLength\r
420 )\r
421{\r
422 UINT32 Index;\r
423 EFI_STATUS Status;\r
424 EFI_PLATFORM_FIRMWARE_BLOB FvBlob;\r
425 TCG_PCR_EVENT_HDR TcgEventHdr;\r
ffde2246
GJ
426 EFI_PHYSICAL_ADDRESS FvOrgBase;\r
427 EFI_PHYSICAL_ADDRESS FvDataBase;\r
428 EFI_PEI_HOB_POINTERS Hob;\r
429 EDKII_MIGRATED_FV_INFO *MigratedFvInfo;\r
0c18794e 430\r
c1d93242
JY
431 //\r
432 // Check if it is in Excluded FV list\r
433 //\r
434 if (mMeasurementExcludedFvPpi != NULL) {\r
435 for (Index = 0; Index < mMeasurementExcludedFvPpi->Count; Index ++) {\r
436 if (mMeasurementExcludedFvPpi->Fv[Index].FvBase == FvBase) {\r
437 DEBUG ((DEBUG_INFO, "The FV which is excluded by TcgPei starts at: 0x%x\n", FvBase));\r
438 DEBUG ((DEBUG_INFO, "The FV which is excluded by TcgPei has the size: 0x%x\n", FvLength));\r
439 return EFI_SUCCESS;\r
440 }\r
441 }\r
442 }\r
443\r
0c18794e 444 //\r
445 // Check whether FV is in the measured FV list.\r
446 //\r
2aadc920 447 for (Index = 0; Index < mMeasuredBaseFvIndex; Index ++) {\r
448 if (mMeasuredBaseFvInfo[Index].BlobBase == FvBase) {\r
0c18794e 449 return EFI_SUCCESS;\r
450 }\r
451 }\r
b3548d32 452\r
ffde2246
GJ
453 //\r
454 // Search the matched migration FV info\r
455 //\r
456 FvOrgBase = FvBase;\r
457 FvDataBase = FvBase;\r
458 Hob.Raw = GetFirstGuidHob (&gEdkiiMigratedFvInfoGuid);\r
459 while (Hob.Raw != NULL) {\r
460 MigratedFvInfo = GET_GUID_HOB_DATA (Hob);\r
461 if ((MigratedFvInfo->FvNewBase == (UINT32) FvBase) && (MigratedFvInfo->FvLength == (UINT32) FvLength)) {\r
462 //\r
463 // Found the migrated FV info\r
464 //\r
465 FvOrgBase = (EFI_PHYSICAL_ADDRESS) (UINTN) MigratedFvInfo->FvOrgBase;\r
466 FvDataBase = (EFI_PHYSICAL_ADDRESS) (UINTN) MigratedFvInfo->FvDataBase;\r
467 break;\r
468 }\r
469 Hob.Raw = GET_NEXT_HOB (Hob);\r
470 Hob.Raw = GetNextGuidHob (&gEdkiiMigratedFvInfoGuid, Hob.Raw);\r
471 }\r
472\r
0c18794e 473 //\r
474 // Measure and record the FV to the TPM\r
475 //\r
ffde2246 476 FvBlob.BlobBase = FvOrgBase;\r
0c18794e 477 FvBlob.BlobLength = FvLength;\r
478\r
479 DEBUG ((DEBUG_INFO, "The FV which is measured by TcgPei starts at: 0x%x\n", FvBlob.BlobBase));\r
480 DEBUG ((DEBUG_INFO, "The FV which is measured by TcgPei has the size: 0x%x\n", FvBlob.BlobLength));\r
481\r
482 TcgEventHdr.PCRIndex = 0;\r
483 TcgEventHdr.EventType = EV_EFI_PLATFORM_FIRMWARE_BLOB;\r
484 TcgEventHdr.EventSize = sizeof (FvBlob);\r
485\r
486 Status = HashLogExtendEvent (\r
3e07c656
JY
487 &mEdkiiTcgPpi,\r
488 0,\r
ffde2246 489 (UINT8*) (UINTN) FvDataBase,\r
0c18794e 490 (UINTN) FvBlob.BlobLength,\r
0c18794e 491 &TcgEventHdr,\r
492 (UINT8*) &FvBlob\r
493 );\r
0c18794e 494\r
495 //\r
496 // Add new FV into the measured FV list.\r
497 //\r
aa8c6e2a
SZ
498 if (mMeasuredBaseFvIndex >= mMeasuredMaxBaseFvIndex) {\r
499 mMeasuredBaseFvInfo = ReallocatePool (\r
500 sizeof (EFI_PLATFORM_FIRMWARE_BLOB) * mMeasuredMaxBaseFvIndex,\r
501 sizeof (EFI_PLATFORM_FIRMWARE_BLOB) * (mMeasuredMaxBaseFvIndex + FIRMWARE_BLOB_GROWTH_STEP),\r
502 mMeasuredBaseFvInfo\r
503 );\r
504 ASSERT (mMeasuredBaseFvInfo != NULL);\r
505 mMeasuredMaxBaseFvIndex = mMeasuredMaxBaseFvIndex + FIRMWARE_BLOB_GROWTH_STEP;\r
0c18794e 506 }\r
507\r
aa8c6e2a
SZ
508 mMeasuredBaseFvInfo[mMeasuredBaseFvIndex].BlobBase = FvBase;\r
509 mMeasuredBaseFvInfo[mMeasuredBaseFvIndex].BlobLength = FvLength;\r
510 mMeasuredBaseFvIndex++;\r
511\r
0c18794e 512 return Status;\r
513}\r
514\r
515/**\r
516 Measure main BIOS.\r
517\r
518 @param[in] PeiServices Describes the list of possible PEI Services.\r
0c18794e 519\r
520 @retval EFI_SUCCESS Operation completed successfully.\r
521 @retval EFI_OUT_OF_RESOURCES No enough memory to log the new event.\r
522 @retval EFI_DEVICE_ERROR The command was unsuccessful.\r
523\r
524**/\r
525EFI_STATUS\r
526EFIAPI\r
527MeasureMainBios (\r
b558f8bc 528 IN EFI_PEI_SERVICES **PeiServices\r
0c18794e 529 )\r
530{\r
531 EFI_STATUS Status;\r
532 UINT32 FvInstances;\r
533 EFI_PEI_FV_HANDLE VolumeHandle;\r
534 EFI_FV_INFO VolumeInfo;\r
535 EFI_PEI_FIRMWARE_VOLUME_PPI *FvPpi;\r
b3548d32 536\r
0c18794e 537 FvInstances = 0;\r
538 while (TRUE) {\r
539 //\r
540 // Traverse all firmware volume instances of Static Core Root of Trust for Measurement\r
541 // (S-CRTM), this firmware volume measure policy can be modified/enhanced by special\r
542 // platform for special CRTM TPM measuring.\r
543 //\r
544 Status = PeiServicesFfsFindNextVolume (FvInstances, &VolumeHandle);\r
545 if (EFI_ERROR (Status)) {\r
546 break;\r
547 }\r
b3548d32 548\r
0c18794e 549 //\r
550 // Measure and record the firmware volume that is dispatched by PeiCore\r
551 //\r
552 Status = PeiServicesFfsGetVolumeInfo (VolumeHandle, &VolumeInfo);\r
553 ASSERT_EFI_ERROR (Status);\r
554 //\r
555 // Locate the corresponding FV_PPI according to founded FV's format guid\r
556 //\r
557 Status = PeiServicesLocatePpi (\r
b3548d32
LG
558 &VolumeInfo.FvFormat,\r
559 0,\r
0c18794e 560 NULL,\r
561 (VOID**)&FvPpi\r
562 );\r
563 if (!EFI_ERROR (Status)) {\r
564 MeasureFvImage ((EFI_PHYSICAL_ADDRESS) (UINTN) VolumeInfo.FvStart, VolumeInfo.FvSize);\r
565 }\r
566\r
567 FvInstances++;\r
568 }\r
569\r
570 return EFI_SUCCESS;\r
571}\r
572\r
573/**\r
dd40a1f8 574 Measure and record the Firmware Volume Information once FvInfoPPI install.\r
0c18794e 575\r
576 @param[in] PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.\r
577 @param[in] NotifyDescriptor Address of the notification descriptor data structure.\r
578 @param[in] Ppi Address of the PPI that was installed.\r
579\r
580 @retval EFI_SUCCESS The FV Info is measured and recorded to TPM.\r
581 @return Others Fail to measure FV.\r
582\r
583**/\r
584EFI_STATUS\r
585EFIAPI\r
d6b926e7 586FirmwareVolumeInfoPpiNotifyCallback (\r
0c18794e 587 IN EFI_PEI_SERVICES **PeiServices,\r
588 IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor,\r
589 IN VOID *Ppi\r
590 )\r
591{\r
592 EFI_PEI_FIRMWARE_VOLUME_INFO_PPI *Fv;\r
593 EFI_STATUS Status;\r
594 EFI_PEI_FIRMWARE_VOLUME_PPI *FvPpi;\r
387208ab 595 UINTN Index;\r
0c18794e 596\r
597 Fv = (EFI_PEI_FIRMWARE_VOLUME_INFO_PPI *) Ppi;\r
598\r
599 //\r
600 // The PEI Core can not dispatch or load files from memory mapped FVs that do not support FvPpi.\r
601 //\r
602 Status = PeiServicesLocatePpi (\r
b3548d32
LG
603 &Fv->FvFormat,\r
604 0,\r
0c18794e 605 NULL,\r
606 (VOID**)&FvPpi\r
607 );\r
608 if (EFI_ERROR (Status)) {\r
609 return EFI_SUCCESS;\r
610 }\r
b3548d32 611\r
0c18794e 612 //\r
613 // This is an FV from an FFS file, and the parent FV must have already been measured,\r
2aadc920 614 // No need to measure twice, so just record the FV and return\r
0c18794e 615 //\r
616 if (Fv->ParentFvName != NULL || Fv->ParentFileName != NULL ) {\r
b3548d32 617\r
aa8c6e2a
SZ
618 if (mMeasuredChildFvIndex >= mMeasuredMaxChildFvIndex) {\r
619 mMeasuredChildFvInfo = ReallocatePool (\r
620 sizeof (EFI_PLATFORM_FIRMWARE_BLOB) * mMeasuredMaxChildFvIndex,\r
621 sizeof (EFI_PLATFORM_FIRMWARE_BLOB) * (mMeasuredMaxChildFvIndex + FIRMWARE_BLOB_GROWTH_STEP),\r
622 mMeasuredChildFvInfo\r
623 );\r
624 ASSERT (mMeasuredChildFvInfo != NULL);\r
625 mMeasuredMaxChildFvIndex = mMeasuredMaxChildFvIndex + FIRMWARE_BLOB_GROWTH_STEP;\r
626 }\r
627 //\r
628 // Check whether FV is in the measured child FV list.\r
629 //\r
630 for (Index = 0; Index < mMeasuredChildFvIndex; Index++) {\r
631 if (mMeasuredChildFvInfo[Index].BlobBase == (EFI_PHYSICAL_ADDRESS) (UINTN) Fv->FvInfo) {\r
632 return EFI_SUCCESS;\r
387208ab 633 }\r
2aadc920 634 }\r
aa8c6e2a
SZ
635 mMeasuredChildFvInfo[mMeasuredChildFvIndex].BlobBase = (EFI_PHYSICAL_ADDRESS) (UINTN) Fv->FvInfo;\r
636 mMeasuredChildFvInfo[mMeasuredChildFvIndex].BlobLength = Fv->FvInfoSize;\r
637 mMeasuredChildFvIndex++;\r
0c18794e 638 return EFI_SUCCESS;\r
639 }\r
640\r
641 return MeasureFvImage ((EFI_PHYSICAL_ADDRESS) (UINTN) Fv->FvInfo, Fv->FvInfoSize);\r
642}\r
643\r
644/**\r
5a500332 645 Set physicalPresenceLifetimeLock, physicalPresenceHWEnable and physicalPresenceCMDEnable bit by corresponding PCDs.\r
646 And lock physical presence if needed.\r
0c18794e 647\r
648 @param[in] PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation\r
649 @param[in] NotifyDescriptor Address of the notification descriptor data structure.\r
650 @param[in] Ppi Address of the PPI that was installed.\r
651\r
652 @retval EFI_SUCCESS Operation completed successfully.\r
653 @retval EFI_ABORTED physicalPresenceCMDEnable is locked.\r
654 @retval EFI_DEVICE_ERROR The command was unsuccessful.\r
655\r
656**/\r
657EFI_STATUS\r
658EFIAPI\r
659PhysicalPresencePpiNotifyCallback (\r
660 IN EFI_PEI_SERVICES **PeiServices,\r
661 IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor,\r
662 IN VOID *Ppi\r
663 )\r
664{\r
665 EFI_STATUS Status;\r
45500265 666 TPM_PERMANENT_FLAGS TpmPermanentFlags;\r
0c18794e 667 PEI_LOCK_PHYSICAL_PRESENCE_PPI *LockPhysicalPresencePpi;\r
5a500332 668 TPM_PHYSICAL_PRESENCE PhysicalPresenceValue;\r
0c18794e 669\r
45500265 670 Status = Tpm12GetCapabilityFlagPermanent (&TpmPermanentFlags);\r
5a500332 671 if (EFI_ERROR (Status)) {\r
672 return Status;\r
0c18794e 673 }\r
674\r
675 //\r
5a500332 676 // 1. Set physicalPresenceLifetimeLock, physicalPresenceHWEnable and physicalPresenceCMDEnable bit by PCDs.\r
0c18794e 677 //\r
45500265 678 if (PcdGetBool (PcdPhysicalPresenceLifetimeLock) && !TpmPermanentFlags.physicalPresenceLifetimeLock) {\r
5a500332 679 //\r
b3548d32 680 // Lock TPM LifetimeLock is required, and LifetimeLock is not locked yet.\r
5a500332 681 //\r
682 PhysicalPresenceValue = TPM_PHYSICAL_PRESENCE_LIFETIME_LOCK;\r
42b85551 683 TpmPermanentFlags.physicalPresenceLifetimeLock = TRUE;\r
5a500332 684\r
685 if (PcdGetBool (PcdPhysicalPresenceCmdEnable)) {\r
686 PhysicalPresenceValue |= TPM_PHYSICAL_PRESENCE_CMD_ENABLE;\r
45500265 687 TpmPermanentFlags.physicalPresenceCMDEnable = TRUE;\r
5a500332 688 } else {\r
689 PhysicalPresenceValue |= TPM_PHYSICAL_PRESENCE_CMD_DISABLE;\r
45500265 690 TpmPermanentFlags.physicalPresenceCMDEnable = FALSE;\r
5a500332 691 }\r
0c18794e 692\r
5a500332 693 if (PcdGetBool (PcdPhysicalPresenceHwEnable)) {\r
694 PhysicalPresenceValue |= TPM_PHYSICAL_PRESENCE_HW_ENABLE;\r
695 } else {\r
696 PhysicalPresenceValue |= TPM_PHYSICAL_PRESENCE_HW_DISABLE;\r
b3548d32
LG
697 }\r
698\r
45500265 699 Status = Tpm12PhysicalPresence (\r
5a500332 700 PhysicalPresenceValue\r
701 );\r
702 if (EFI_ERROR (Status)) {\r
703 return Status;\r
704 }\r
705 }\r
b3548d32 706\r
5a500332 707 //\r
708 // 2. Lock physical presence if it is required.\r
709 //\r
710 LockPhysicalPresencePpi = (PEI_LOCK_PHYSICAL_PRESENCE_PPI *) Ppi;\r
711 if (!LockPhysicalPresencePpi->LockPhysicalPresence ((CONST EFI_PEI_SERVICES**) PeiServices)) {\r
712 return EFI_SUCCESS;\r
0c18794e 713 }\r
714\r
45500265
MK
715 if (!TpmPermanentFlags.physicalPresenceCMDEnable) {\r
716 if (TpmPermanentFlags.physicalPresenceLifetimeLock) {\r
0c18794e 717 //\r
718 // physicalPresenceCMDEnable is locked, can't change.\r
719 //\r
720 return EFI_ABORTED;\r
721 }\r
722\r
723 //\r
724 // Enable physical presence command\r
725 // It is necessary in order to lock physical presence\r
726 //\r
45500265 727 Status = Tpm12PhysicalPresence (\r
0c18794e 728 TPM_PHYSICAL_PRESENCE_CMD_ENABLE\r
729 );\r
730 if (EFI_ERROR (Status)) {\r
731 return Status;\r
732 }\r
733 }\r
734\r
735 //\r
736 // Lock physical presence\r
b3548d32 737 //\r
45500265 738 Status = Tpm12PhysicalPresence (\r
0c18794e 739 TPM_PHYSICAL_PRESENCE_LOCK\r
740 );\r
741 return Status;\r
742}\r
743\r
744/**\r
d6b926e7 745 Check if TPM chip is activated or not.\r
0c18794e 746\r
747 @param[in] PeiServices Describes the list of possible PEI Services.\r
0c18794e 748\r
749 @retval TRUE TPM is activated.\r
750 @retval FALSE TPM is deactivated.\r
751\r
752**/\r
753BOOLEAN\r
0c18794e 754IsTpmUsable (\r
45500265 755 VOID\r
0c18794e 756 )\r
757{\r
45500265
MK
758 EFI_STATUS Status;\r
759 TPM_PERMANENT_FLAGS TpmPermanentFlags;\r
0c18794e 760\r
45500265 761 Status = Tpm12GetCapabilityFlagPermanent (&TpmPermanentFlags);\r
0c18794e 762 if (EFI_ERROR (Status)) {\r
763 return FALSE;\r
764 }\r
45500265 765 return (BOOLEAN)(!TpmPermanentFlags.deactivated);\r
0c18794e 766}\r
767\r
768/**\r
769 Do measurement after memory is ready.\r
770\r
771 @param[in] PeiServices Describes the list of possible PEI Services.\r
772\r
773 @retval EFI_SUCCESS Operation completed successfully.\r
774 @retval EFI_OUT_OF_RESOURCES No enough memory to log the new event.\r
775 @retval EFI_DEVICE_ERROR The command was unsuccessful.\r
776\r
777**/\r
778EFI_STATUS\r
779EFIAPI\r
780PeimEntryMP (\r
781 IN EFI_PEI_SERVICES **PeiServices\r
782 )\r
783{\r
784 EFI_STATUS Status;\r
0c18794e 785\r
c1d93242 786 Status = PeiServicesLocatePpi (\r
b3548d32
LG
787 &gEfiPeiFirmwareVolumeInfoMeasurementExcludedPpiGuid,\r
788 0,\r
c1d93242
JY
789 NULL,\r
790 (VOID**)&mMeasurementExcludedFvPpi\r
791 );\r
792 // Do not check status, because it is optional\r
793\r
b558f8bc 794 Status = Tpm12RequestUseTpm ();\r
0c18794e 795 if (EFI_ERROR (Status)) {\r
796 return Status;\r
797 }\r
798\r
45500265 799 if (IsTpmUsable ()) {\r
c1d93242 800 if (PcdGet8 (PcdTpmScrtmPolicy) == 1) {\r
b558f8bc 801 Status = MeasureCRTMVersion (PeiServices);\r
c1d93242 802 }\r
0c18794e 803\r
b558f8bc 804 Status = MeasureMainBios (PeiServices);\r
b3548d32 805 }\r
0c18794e 806\r
807 //\r
808 // Post callbacks:\r
809 // 1). for the FvInfoPpi services to measure and record\r
810 // the additional Fvs to TPM\r
b3548d32 811 // 2). for the OperatorPresencePpi service to determine whether to\r
0c18794e 812 // lock the TPM\r
813 //\r
814 Status = PeiServicesNotifyPpi (&mNotifyList[0]);\r
815 ASSERT_EFI_ERROR (Status);\r
816\r
3e07c656
JY
817 //\r
818 // install Tcg Services\r
819 //\r
820 Status = PeiServicesInstallPpi (&mTcgPpiList);\r
821 ASSERT_EFI_ERROR (Status);\r
822\r
0c18794e 823 return Status;\r
824}\r
825\r
826/**\r
827 Entry point of this module.\r
828\r
829 @param[in] FileHandle Handle of the file being invoked.\r
830 @param[in] PeiServices Describes the list of possible PEI Services.\r
831\r
832 @return Status.\r
833\r
834**/\r
835EFI_STATUS\r
836EFIAPI\r
837PeimEntryMA (\r
838 IN EFI_PEI_FILE_HANDLE FileHandle,\r
839 IN CONST EFI_PEI_SERVICES **PeiServices\r
840 )\r
841{\r
842 EFI_STATUS Status;\r
83a276f6 843 EFI_STATUS Status2;\r
0c18794e 844 EFI_BOOT_MODE BootMode;\r
0c18794e 845\r
c1d93242 846 if (!CompareGuid (PcdGetPtr(PcdTpmInstanceGuid), &gEfiTpmDeviceInstanceTpm12Guid)){\r
e905fbb0 847 DEBUG ((DEBUG_ERROR, "No TPM12 instance required!\n"));\r
c1d93242
JY
848 return EFI_UNSUPPORTED;\r
849 }\r
850\r
3dd05ac3 851 if (GetFirstGuidHob (&gTpmErrorHobGuid) != NULL) {\r
e905fbb0 852 DEBUG ((DEBUG_ERROR, "TPM error!\n"));\r
3dd05ac3
JY
853 return EFI_DEVICE_ERROR;\r
854 }\r
855\r
055c829c 856 //\r
857 // Initialize TPM device\r
858 //\r
859 Status = PeiServicesGetBootMode (&BootMode);\r
860 ASSERT_EFI_ERROR (Status);\r
861\r
862 //\r
863 // In S3 path, skip shadow logic. no measurement is required\r
864 //\r
865 if (BootMode != BOOT_ON_S3_RESUME) {\r
866 Status = (**PeiServices).RegisterForShadow(FileHandle);\r
867 if (Status == EFI_ALREADY_STARTED) {\r
868 mImageInMemory = TRUE;\r
869 } else if (Status == EFI_NOT_FOUND) {\r
870 ASSERT_EFI_ERROR (Status);\r
871 }\r
0c18794e 872 }\r
873\r
874 if (!mImageInMemory) {\r
b558f8bc 875 Status = Tpm12RequestUseTpm ();\r
0c18794e 876 if (EFI_ERROR (Status)) {\r
877 DEBUG ((DEBUG_ERROR, "TPM not detected!\n"));\r
83a276f6 878 goto Done;\r
0c18794e 879 }\r
880\r
c1d93242 881 if (PcdGet8 (PcdTpmInitializationPolicy) == 1) {\r
45500265
MK
882 if (BootMode == BOOT_ON_S3_RESUME) {\r
883 Status = Tpm12Startup (TPM_ST_STATE);\r
884 } else {\r
885 Status = Tpm12Startup (TPM_ST_CLEAR);\r
886 }\r
c1d93242 887 if (EFI_ERROR (Status) ) {\r
83a276f6 888 goto Done;\r
c1d93242 889 }\r
0c18794e 890 }\r
6f6c7857 891\r
892 //\r
893 // TpmSelfTest is optional on S3 path, skip it to save S3 time\r
894 //\r
895 if (BootMode != BOOT_ON_S3_RESUME) {\r
45500265 896 Status = Tpm12ContinueSelfTest ();\r
6f6c7857 897 if (EFI_ERROR (Status)) {\r
83a276f6 898 goto Done;\r
6f6c7857 899 }\r
0c18794e 900 }\r
6f6c7857 901\r
83a276f6 902 //\r
dd40a1f8 903 // Only install TpmInitializedPpi on success\r
83a276f6 904 //\r
0c18794e 905 Status = PeiServicesInstallPpi (&mTpmInitializedPpiList);\r
906 ASSERT_EFI_ERROR (Status);\r
907 }\r
908\r
909 if (mImageInMemory) {\r
910 Status = PeimEntryMP ((EFI_PEI_SERVICES**)PeiServices);\r
83a276f6 911 return Status;\r
0c18794e 912 }\r
913\r
83a276f6 914Done:\r
3dd05ac3 915 if (EFI_ERROR (Status)) {\r
e905fbb0 916 DEBUG ((DEBUG_ERROR, "TPM error! Build Hob\n"));\r
3dd05ac3
JY
917 BuildGuidHob (&gTpmErrorHobGuid,0);\r
918 REPORT_STATUS_CODE (\r
919 EFI_ERROR_CODE | EFI_ERROR_MINOR,\r
920 (PcdGet32 (PcdStatusCodeSubClassTpmDevice) | EFI_P_EC_INTERFACE_ERROR)\r
921 );\r
922 }\r
83a276f6 923 //\r
dd40a1f8 924 // Always install TpmInitializationDonePpi no matter success or fail.\r
83a276f6
JY
925 // Other driver can know TPM initialization state by TpmInitializedPpi.\r
926 //\r
927 Status2 = PeiServicesInstallPpi (&mTpmInitializationDonePpiList);\r
928 ASSERT_EFI_ERROR (Status2);\r
929\r
0c18794e 930 return Status;\r
931}\r