]> git.proxmox.com Git - mirror_edk2.git/blame - SecurityPkg/Tcg/TcgPei/TcgPei.c
UefiCpuPkg: Move AsmRelocateApLoopStart from Mpfuncs.nasm to AmdSev.nasm
[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
c411b485 42BOOLEAN mImageInMemory = FALSE;\r
0c18794e 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
c411b485
MK
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
3e07c656
JY
83 );\r
84\r
c411b485 85EDKII_TCG_PPI mEdkiiTcgPpi = {\r
3e07c656
JY
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
c411b485 98#define FIRMWARE_BLOB_GROWTH_STEP 4\r
aa8c6e2a 99\r
c411b485
MK
100EFI_PLATFORM_FIRMWARE_BLOB *mMeasuredBaseFvInfo;\r
101UINT32 mMeasuredMaxBaseFvIndex = 0;\r
102UINT32 mMeasuredBaseFvIndex = 0;\r
2aadc920 103\r
c411b485
MK
104EFI_PLATFORM_FIRMWARE_BLOB *mMeasuredChildFvInfo;\r
105UINT32 mMeasuredMaxChildFvIndex = 0;\r
106UINT32 mMeasuredChildFvIndex = 0;\r
2aadc920 107\r
c411b485 108EFI_PEI_FIRMWARE_VOLUME_INFO_MEASUREMENT_EXCLUDED_PPI *mMeasurementExcludedFvPpi;\r
c1d93242 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
c411b485
MK
123 IN EFI_PEI_SERVICES **PeiServices,\r
124 IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor,\r
125 IN VOID *Ppi\r
0c18794e 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
c411b485
MK
142 IN EFI_PEI_SERVICES **PeiServices,\r
143 IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor,\r
144 IN VOID *Ppi\r
0c18794e 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
c411b485
MK
161 IN EFI_PEI_SERVICES **PeiServices,\r
162 IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor,\r
163 IN VOID *Ppi\r
2aadc920 164 );\r
165\r
c411b485 166EFI_PEI_NOTIFY_DESCRIPTOR mNotifyList[] = {\r
0c18794e 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
c411b485
MK
207 IN EFI_PEI_SERVICES **PeiServices,\r
208 IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor,\r
209 IN VOID *Ppi\r
2aadc920 210 )\r
b3548d32 211{\r
c411b485 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
c411b485 221 MeasuredHobData = BuildGuidHob (\r
0758c830 222 &gMeasuredFvHobGuid,\r
c411b485 223 sizeof (UINTN) + sizeof (EFI_PLATFORM_FIRMWARE_BLOB) * (mMeasuredBaseFvIndex + mMeasuredChildFvIndex)\r
0758c830 224 );\r
2aadc920 225\r
c411b485 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
c411b485 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
c411b485 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
c411b485
MK
303 IN EDKII_TCG_PPI *This,\r
304 IN UINT64 Flags,\r
305 IN UINT8 *HashData,\r
306 IN UINTN HashDataLen,\r
307 IN TCG_PCR_EVENT_HDR *NewEventHdr,\r
308 IN UINT8 *NewEventData\r
0c18794e 309 )\r
310{\r
c411b485
MK
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
c411b485
MK
340 &gTcgEventEntryHobGuid,\r
341 sizeof (*NewEventHdr) + NewEventHdr->EventSize\r
342 );\r
0c18794e 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
c411b485 349 HobData = (VOID *)((UINT8 *)HobData + sizeof (*NewEventHdr));\r
0c18794e 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
c411b485 355 BuildGuidHob (&gTpmErrorHobGuid, 0);\r
6f785cfc
JY
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
c411b485 362\r
6f785cfc 363 return Status;\r
0c18794e 364}\r
365\r
366/**\r
367 Measure CRTM version.\r
368\r
369 @param[in] PeiServices Describes the list of possible PEI Services.\r
0c18794e 370\r
371 @retval EFI_SUCCESS Operation completed successfully.\r
372 @retval EFI_OUT_OF_RESOURCES No enough memory to log the new event.\r
373 @retval EFI_DEVICE_ERROR The command was unsuccessful.\r
374\r
375**/\r
376EFI_STATUS\r
377EFIAPI\r
378MeasureCRTMVersion (\r
c411b485 379 IN EFI_PEI_SERVICES **PeiServices\r
0c18794e 380 )\r
381{\r
c411b485 382 TCG_PCR_EVENT_HDR TcgEventHdr;\r
0c18794e 383\r
384 //\r
333a53ee 385 // Use FirmwareVersion string to represent CRTM version.\r
0c18794e 386 // OEMs should get real CRTM version string and measure it.\r
387 //\r
388\r
389 TcgEventHdr.PCRIndex = 0;\r
390 TcgEventHdr.EventType = EV_S_CRTM_VERSION;\r
c411b485 391 TcgEventHdr.EventSize = (UINT32)StrSize ((CHAR16 *)PcdGetPtr (PcdFirmwareVersionString));\r
333a53ee 392\r
0c18794e 393 return HashLogExtendEvent (\r
3e07c656
JY
394 &mEdkiiTcgPpi,\r
395 0,\r
c411b485 396 (UINT8 *)PcdGetPtr (PcdFirmwareVersionString),\r
0c18794e 397 TcgEventHdr.EventSize,\r
0c18794e 398 &TcgEventHdr,\r
c411b485 399 (UINT8 *)PcdGetPtr (PcdFirmwareVersionString)\r
0c18794e 400 );\r
401}\r
402\r
403/**\r
b3548d32
LG
404 Measure FV image.\r
405 Add it into the measured FV list after the FV is measured successfully.\r
0c18794e 406\r
407 @param[in] FvBase Base address of FV image.\r
408 @param[in] FvLength Length of FV image.\r
409\r
b3548d32 410 @retval EFI_SUCCESS Fv image is measured successfully\r
0c18794e 411 or it has been already measured.\r
412 @retval EFI_OUT_OF_RESOURCES No enough memory to log the new event.\r
413 @retval EFI_DEVICE_ERROR The command was unsuccessful.\r
414\r
415**/\r
416EFI_STATUS\r
417EFIAPI\r
418MeasureFvImage (\r
c411b485
MK
419 IN EFI_PHYSICAL_ADDRESS FvBase,\r
420 IN UINT64 FvLength\r
0c18794e 421 )\r
422{\r
c411b485
MK
423 UINT32 Index;\r
424 EFI_STATUS Status;\r
425 EFI_PLATFORM_FIRMWARE_BLOB FvBlob;\r
426 TCG_PCR_EVENT_HDR TcgEventHdr;\r
427 EFI_PHYSICAL_ADDRESS FvOrgBase;\r
428 EFI_PHYSICAL_ADDRESS FvDataBase;\r
429 EFI_PEI_HOB_POINTERS Hob;\r
430 EDKII_MIGRATED_FV_INFO *MigratedFvInfo;\r
0c18794e 431\r
c1d93242
JY
432 //\r
433 // Check if it is in Excluded FV list\r
434 //\r
435 if (mMeasurementExcludedFvPpi != NULL) {\r
c411b485 436 for (Index = 0; Index < mMeasurementExcludedFvPpi->Count; Index++) {\r
c1d93242
JY
437 if (mMeasurementExcludedFvPpi->Fv[Index].FvBase == FvBase) {\r
438 DEBUG ((DEBUG_INFO, "The FV which is excluded by TcgPei starts at: 0x%x\n", FvBase));\r
439 DEBUG ((DEBUG_INFO, "The FV which is excluded by TcgPei has the size: 0x%x\n", FvLength));\r
440 return EFI_SUCCESS;\r
441 }\r
442 }\r
443 }\r
444\r
0c18794e 445 //\r
446 // Check whether FV is in the measured FV list.\r
447 //\r
c411b485 448 for (Index = 0; Index < mMeasuredBaseFvIndex; Index++) {\r
2aadc920 449 if (mMeasuredBaseFvInfo[Index].BlobBase == FvBase) {\r
0c18794e 450 return EFI_SUCCESS;\r
451 }\r
452 }\r
b3548d32 453\r
ffde2246
GJ
454 //\r
455 // Search the matched migration FV info\r
456 //\r
457 FvOrgBase = FvBase;\r
458 FvDataBase = FvBase;\r
c411b485 459 Hob.Raw = GetFirstGuidHob (&gEdkiiMigratedFvInfoGuid);\r
ffde2246
GJ
460 while (Hob.Raw != NULL) {\r
461 MigratedFvInfo = GET_GUID_HOB_DATA (Hob);\r
c411b485 462 if ((MigratedFvInfo->FvNewBase == (UINT32)FvBase) && (MigratedFvInfo->FvLength == (UINT32)FvLength)) {\r
ffde2246
GJ
463 //\r
464 // Found the migrated FV info\r
465 //\r
c411b485
MK
466 FvOrgBase = (EFI_PHYSICAL_ADDRESS)(UINTN)MigratedFvInfo->FvOrgBase;\r
467 FvDataBase = (EFI_PHYSICAL_ADDRESS)(UINTN)MigratedFvInfo->FvDataBase;\r
ffde2246
GJ
468 break;\r
469 }\r
c411b485 470\r
ffde2246
GJ
471 Hob.Raw = GET_NEXT_HOB (Hob);\r
472 Hob.Raw = GetNextGuidHob (&gEdkiiMigratedFvInfoGuid, Hob.Raw);\r
473 }\r
474\r
0c18794e 475 //\r
476 // Measure and record the FV to the TPM\r
477 //\r
ffde2246 478 FvBlob.BlobBase = FvOrgBase;\r
0c18794e 479 FvBlob.BlobLength = FvLength;\r
480\r
481 DEBUG ((DEBUG_INFO, "The FV which is measured by TcgPei starts at: 0x%x\n", FvBlob.BlobBase));\r
482 DEBUG ((DEBUG_INFO, "The FV which is measured by TcgPei has the size: 0x%x\n", FvBlob.BlobLength));\r
483\r
c411b485 484 TcgEventHdr.PCRIndex = 0;\r
0c18794e 485 TcgEventHdr.EventType = EV_EFI_PLATFORM_FIRMWARE_BLOB;\r
486 TcgEventHdr.EventSize = sizeof (FvBlob);\r
487\r
488 Status = HashLogExtendEvent (\r
3e07c656
JY
489 &mEdkiiTcgPpi,\r
490 0,\r
c411b485
MK
491 (UINT8 *)(UINTN)FvDataBase,\r
492 (UINTN)FvBlob.BlobLength,\r
0c18794e 493 &TcgEventHdr,\r
c411b485 494 (UINT8 *)&FvBlob\r
0c18794e 495 );\r
0c18794e 496\r
497 //\r
498 // Add new FV into the measured FV list.\r
499 //\r
aa8c6e2a
SZ
500 if (mMeasuredBaseFvIndex >= mMeasuredMaxBaseFvIndex) {\r
501 mMeasuredBaseFvInfo = ReallocatePool (\r
502 sizeof (EFI_PLATFORM_FIRMWARE_BLOB) * mMeasuredMaxBaseFvIndex,\r
503 sizeof (EFI_PLATFORM_FIRMWARE_BLOB) * (mMeasuredMaxBaseFvIndex + FIRMWARE_BLOB_GROWTH_STEP),\r
504 mMeasuredBaseFvInfo\r
505 );\r
506 ASSERT (mMeasuredBaseFvInfo != NULL);\r
507 mMeasuredMaxBaseFvIndex = mMeasuredMaxBaseFvIndex + FIRMWARE_BLOB_GROWTH_STEP;\r
0c18794e 508 }\r
509\r
aa8c6e2a
SZ
510 mMeasuredBaseFvInfo[mMeasuredBaseFvIndex].BlobBase = FvBase;\r
511 mMeasuredBaseFvInfo[mMeasuredBaseFvIndex].BlobLength = FvLength;\r
512 mMeasuredBaseFvIndex++;\r
513\r
0c18794e 514 return Status;\r
515}\r
516\r
517/**\r
518 Measure main BIOS.\r
519\r
520 @param[in] PeiServices Describes the list of possible PEI Services.\r
0c18794e 521\r
522 @retval EFI_SUCCESS Operation completed successfully.\r
523 @retval EFI_OUT_OF_RESOURCES No enough memory to log the new event.\r
524 @retval EFI_DEVICE_ERROR The command was unsuccessful.\r
525\r
526**/\r
527EFI_STATUS\r
528EFIAPI\r
529MeasureMainBios (\r
c411b485 530 IN EFI_PEI_SERVICES **PeiServices\r
0c18794e 531 )\r
532{\r
c411b485
MK
533 EFI_STATUS Status;\r
534 UINT32 FvInstances;\r
535 EFI_PEI_FV_HANDLE VolumeHandle;\r
536 EFI_FV_INFO VolumeInfo;\r
537 EFI_PEI_FIRMWARE_VOLUME_PPI *FvPpi;\r
b3548d32 538\r
c411b485 539 FvInstances = 0;\r
0c18794e 540 while (TRUE) {\r
541 //\r
542 // Traverse all firmware volume instances of Static Core Root of Trust for Measurement\r
543 // (S-CRTM), this firmware volume measure policy can be modified/enhanced by special\r
544 // platform for special CRTM TPM measuring.\r
545 //\r
546 Status = PeiServicesFfsFindNextVolume (FvInstances, &VolumeHandle);\r
547 if (EFI_ERROR (Status)) {\r
548 break;\r
549 }\r
b3548d32 550\r
0c18794e 551 //\r
552 // Measure and record the firmware volume that is dispatched by PeiCore\r
553 //\r
554 Status = PeiServicesFfsGetVolumeInfo (VolumeHandle, &VolumeInfo);\r
555 ASSERT_EFI_ERROR (Status);\r
556 //\r
557 // Locate the corresponding FV_PPI according to founded FV's format guid\r
558 //\r
559 Status = PeiServicesLocatePpi (\r
b3548d32
LG
560 &VolumeInfo.FvFormat,\r
561 0,\r
0c18794e 562 NULL,\r
c411b485 563 (VOID **)&FvPpi\r
0c18794e 564 );\r
565 if (!EFI_ERROR (Status)) {\r
c411b485 566 MeasureFvImage ((EFI_PHYSICAL_ADDRESS)(UINTN)VolumeInfo.FvStart, VolumeInfo.FvSize);\r
0c18794e 567 }\r
568\r
569 FvInstances++;\r
570 }\r
571\r
572 return EFI_SUCCESS;\r
573}\r
574\r
575/**\r
dd40a1f8 576 Measure and record the Firmware Volume Information once FvInfoPPI install.\r
0c18794e 577\r
578 @param[in] PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.\r
579 @param[in] NotifyDescriptor Address of the notification descriptor data structure.\r
580 @param[in] Ppi Address of the PPI that was installed.\r
581\r
582 @retval EFI_SUCCESS The FV Info is measured and recorded to TPM.\r
583 @return Others Fail to measure FV.\r
584\r
585**/\r
586EFI_STATUS\r
587EFIAPI\r
d6b926e7 588FirmwareVolumeInfoPpiNotifyCallback (\r
c411b485
MK
589 IN EFI_PEI_SERVICES **PeiServices,\r
590 IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor,\r
591 IN VOID *Ppi\r
0c18794e 592 )\r
593{\r
594 EFI_PEI_FIRMWARE_VOLUME_INFO_PPI *Fv;\r
595 EFI_STATUS Status;\r
596 EFI_PEI_FIRMWARE_VOLUME_PPI *FvPpi;\r
387208ab 597 UINTN Index;\r
0c18794e 598\r
c411b485 599 Fv = (EFI_PEI_FIRMWARE_VOLUME_INFO_PPI *)Ppi;\r
0c18794e 600\r
601 //\r
602 // The PEI Core can not dispatch or load files from memory mapped FVs that do not support FvPpi.\r
603 //\r
604 Status = PeiServicesLocatePpi (\r
b3548d32
LG
605 &Fv->FvFormat,\r
606 0,\r
0c18794e 607 NULL,\r
c411b485 608 (VOID **)&FvPpi\r
0c18794e 609 );\r
610 if (EFI_ERROR (Status)) {\r
611 return EFI_SUCCESS;\r
612 }\r
b3548d32 613\r
0c18794e 614 //\r
615 // This is an FV from an FFS file, and the parent FV must have already been measured,\r
2aadc920 616 // No need to measure twice, so just record the FV and return\r
0c18794e 617 //\r
c411b485 618 if ((Fv->ParentFvName != NULL) || (Fv->ParentFileName != NULL)) {\r
aa8c6e2a
SZ
619 if (mMeasuredChildFvIndex >= mMeasuredMaxChildFvIndex) {\r
620 mMeasuredChildFvInfo = ReallocatePool (\r
621 sizeof (EFI_PLATFORM_FIRMWARE_BLOB) * mMeasuredMaxChildFvIndex,\r
622 sizeof (EFI_PLATFORM_FIRMWARE_BLOB) * (mMeasuredMaxChildFvIndex + FIRMWARE_BLOB_GROWTH_STEP),\r
623 mMeasuredChildFvInfo\r
624 );\r
625 ASSERT (mMeasuredChildFvInfo != NULL);\r
626 mMeasuredMaxChildFvIndex = mMeasuredMaxChildFvIndex + FIRMWARE_BLOB_GROWTH_STEP;\r
627 }\r
c411b485 628\r
aa8c6e2a
SZ
629 //\r
630 // Check whether FV is in the measured child FV list.\r
631 //\r
632 for (Index = 0; Index < mMeasuredChildFvIndex; Index++) {\r
c411b485 633 if (mMeasuredChildFvInfo[Index].BlobBase == (EFI_PHYSICAL_ADDRESS)(UINTN)Fv->FvInfo) {\r
aa8c6e2a 634 return EFI_SUCCESS;\r
387208ab 635 }\r
2aadc920 636 }\r
c411b485
MK
637\r
638 mMeasuredChildFvInfo[mMeasuredChildFvIndex].BlobBase = (EFI_PHYSICAL_ADDRESS)(UINTN)Fv->FvInfo;\r
aa8c6e2a
SZ
639 mMeasuredChildFvInfo[mMeasuredChildFvIndex].BlobLength = Fv->FvInfoSize;\r
640 mMeasuredChildFvIndex++;\r
0c18794e 641 return EFI_SUCCESS;\r
642 }\r
643\r
c411b485 644 return MeasureFvImage ((EFI_PHYSICAL_ADDRESS)(UINTN)Fv->FvInfo, Fv->FvInfoSize);\r
0c18794e 645}\r
646\r
647/**\r
5a500332 648 Set physicalPresenceLifetimeLock, physicalPresenceHWEnable and physicalPresenceCMDEnable bit by corresponding PCDs.\r
649 And lock physical presence if needed.\r
0c18794e 650\r
651 @param[in] PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation\r
652 @param[in] NotifyDescriptor Address of the notification descriptor data structure.\r
653 @param[in] Ppi Address of the PPI that was installed.\r
654\r
655 @retval EFI_SUCCESS Operation completed successfully.\r
656 @retval EFI_ABORTED physicalPresenceCMDEnable is locked.\r
657 @retval EFI_DEVICE_ERROR The command was unsuccessful.\r
658\r
659**/\r
660EFI_STATUS\r
661EFIAPI\r
662PhysicalPresencePpiNotifyCallback (\r
c411b485
MK
663 IN EFI_PEI_SERVICES **PeiServices,\r
664 IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor,\r
665 IN VOID *Ppi\r
0c18794e 666 )\r
667{\r
c411b485
MK
668 EFI_STATUS Status;\r
669 TPM_PERMANENT_FLAGS TpmPermanentFlags;\r
670 PEI_LOCK_PHYSICAL_PRESENCE_PPI *LockPhysicalPresencePpi;\r
671 TPM_PHYSICAL_PRESENCE PhysicalPresenceValue;\r
0c18794e 672\r
45500265 673 Status = Tpm12GetCapabilityFlagPermanent (&TpmPermanentFlags);\r
5a500332 674 if (EFI_ERROR (Status)) {\r
675 return Status;\r
0c18794e 676 }\r
677\r
678 //\r
5a500332 679 // 1. Set physicalPresenceLifetimeLock, physicalPresenceHWEnable and physicalPresenceCMDEnable bit by PCDs.\r
0c18794e 680 //\r
45500265 681 if (PcdGetBool (PcdPhysicalPresenceLifetimeLock) && !TpmPermanentFlags.physicalPresenceLifetimeLock) {\r
5a500332 682 //\r
b3548d32 683 // Lock TPM LifetimeLock is required, and LifetimeLock is not locked yet.\r
5a500332 684 //\r
c411b485 685 PhysicalPresenceValue = TPM_PHYSICAL_PRESENCE_LIFETIME_LOCK;\r
42b85551 686 TpmPermanentFlags.physicalPresenceLifetimeLock = TRUE;\r
5a500332 687\r
688 if (PcdGetBool (PcdPhysicalPresenceCmdEnable)) {\r
c411b485 689 PhysicalPresenceValue |= TPM_PHYSICAL_PRESENCE_CMD_ENABLE;\r
45500265 690 TpmPermanentFlags.physicalPresenceCMDEnable = TRUE;\r
5a500332 691 } else {\r
c411b485 692 PhysicalPresenceValue |= TPM_PHYSICAL_PRESENCE_CMD_DISABLE;\r
45500265 693 TpmPermanentFlags.physicalPresenceCMDEnable = FALSE;\r
5a500332 694 }\r
0c18794e 695\r
5a500332 696 if (PcdGetBool (PcdPhysicalPresenceHwEnable)) {\r
697 PhysicalPresenceValue |= TPM_PHYSICAL_PRESENCE_HW_ENABLE;\r
698 } else {\r
699 PhysicalPresenceValue |= TPM_PHYSICAL_PRESENCE_HW_DISABLE;\r
b3548d32
LG
700 }\r
701\r
45500265 702 Status = Tpm12PhysicalPresence (\r
5a500332 703 PhysicalPresenceValue\r
704 );\r
705 if (EFI_ERROR (Status)) {\r
706 return Status;\r
707 }\r
708 }\r
b3548d32 709\r
5a500332 710 //\r
711 // 2. Lock physical presence if it is required.\r
712 //\r
c411b485
MK
713 LockPhysicalPresencePpi = (PEI_LOCK_PHYSICAL_PRESENCE_PPI *)Ppi;\r
714 if (!LockPhysicalPresencePpi->LockPhysicalPresence ((CONST EFI_PEI_SERVICES **)PeiServices)) {\r
5a500332 715 return EFI_SUCCESS;\r
0c18794e 716 }\r
717\r
45500265
MK
718 if (!TpmPermanentFlags.physicalPresenceCMDEnable) {\r
719 if (TpmPermanentFlags.physicalPresenceLifetimeLock) {\r
0c18794e 720 //\r
721 // physicalPresenceCMDEnable is locked, can't change.\r
722 //\r
723 return EFI_ABORTED;\r
724 }\r
725\r
726 //\r
727 // Enable physical presence command\r
728 // It is necessary in order to lock physical presence\r
729 //\r
45500265 730 Status = Tpm12PhysicalPresence (\r
0c18794e 731 TPM_PHYSICAL_PRESENCE_CMD_ENABLE\r
732 );\r
733 if (EFI_ERROR (Status)) {\r
734 return Status;\r
735 }\r
736 }\r
737\r
738 //\r
739 // Lock physical presence\r
b3548d32 740 //\r
45500265 741 Status = Tpm12PhysicalPresence (\r
c411b485
MK
742 TPM_PHYSICAL_PRESENCE_LOCK\r
743 );\r
0c18794e 744 return Status;\r
745}\r
746\r
747/**\r
d6b926e7 748 Check if TPM chip is activated or not.\r
0c18794e 749\r
750 @param[in] PeiServices Describes the list of possible PEI Services.\r
0c18794e 751\r
752 @retval TRUE TPM is activated.\r
753 @retval FALSE TPM is deactivated.\r
754\r
755**/\r
756BOOLEAN\r
0c18794e 757IsTpmUsable (\r
45500265 758 VOID\r
0c18794e 759 )\r
760{\r
45500265
MK
761 EFI_STATUS Status;\r
762 TPM_PERMANENT_FLAGS TpmPermanentFlags;\r
0c18794e 763\r
45500265 764 Status = Tpm12GetCapabilityFlagPermanent (&TpmPermanentFlags);\r
0c18794e 765 if (EFI_ERROR (Status)) {\r
766 return FALSE;\r
767 }\r
c411b485 768\r
45500265 769 return (BOOLEAN)(!TpmPermanentFlags.deactivated);\r
0c18794e 770}\r
771\r
772/**\r
773 Do measurement after memory is ready.\r
774\r
775 @param[in] PeiServices Describes the list of possible PEI Services.\r
776\r
777 @retval EFI_SUCCESS Operation completed successfully.\r
778 @retval EFI_OUT_OF_RESOURCES No enough memory to log the new event.\r
779 @retval EFI_DEVICE_ERROR The command was unsuccessful.\r
780\r
781**/\r
782EFI_STATUS\r
783EFIAPI\r
784PeimEntryMP (\r
c411b485 785 IN EFI_PEI_SERVICES **PeiServices\r
0c18794e 786 )\r
787{\r
c411b485 788 EFI_STATUS Status;\r
0c18794e 789\r
c1d93242 790 Status = PeiServicesLocatePpi (\r
c411b485
MK
791 &gEfiPeiFirmwareVolumeInfoMeasurementExcludedPpiGuid,\r
792 0,\r
793 NULL,\r
794 (VOID **)&mMeasurementExcludedFvPpi\r
795 );\r
c1d93242
JY
796 // Do not check status, because it is optional\r
797\r
b558f8bc 798 Status = Tpm12RequestUseTpm ();\r
0c18794e 799 if (EFI_ERROR (Status)) {\r
800 return Status;\r
801 }\r
802\r
45500265 803 if (IsTpmUsable ()) {\r
c1d93242 804 if (PcdGet8 (PcdTpmScrtmPolicy) == 1) {\r
b558f8bc 805 Status = MeasureCRTMVersion (PeiServices);\r
c1d93242 806 }\r
0c18794e 807\r
b558f8bc 808 Status = MeasureMainBios (PeiServices);\r
b3548d32 809 }\r
0c18794e 810\r
811 //\r
812 // Post callbacks:\r
813 // 1). for the FvInfoPpi services to measure and record\r
814 // the additional Fvs to TPM\r
b3548d32 815 // 2). for the OperatorPresencePpi service to determine whether to\r
0c18794e 816 // lock the TPM\r
817 //\r
818 Status = PeiServicesNotifyPpi (&mNotifyList[0]);\r
819 ASSERT_EFI_ERROR (Status);\r
820\r
3e07c656
JY
821 //\r
822 // install Tcg Services\r
823 //\r
824 Status = PeiServicesInstallPpi (&mTcgPpiList);\r
825 ASSERT_EFI_ERROR (Status);\r
826\r
0c18794e 827 return Status;\r
828}\r
829\r
830/**\r
831 Entry point of this module.\r
832\r
833 @param[in] FileHandle Handle of the file being invoked.\r
834 @param[in] PeiServices Describes the list of possible PEI Services.\r
835\r
836 @return Status.\r
837\r
838**/\r
839EFI_STATUS\r
840EFIAPI\r
841PeimEntryMA (\r
c411b485
MK
842 IN EFI_PEI_FILE_HANDLE FileHandle,\r
843 IN CONST EFI_PEI_SERVICES **PeiServices\r
0c18794e 844 )\r
845{\r
c411b485
MK
846 EFI_STATUS Status;\r
847 EFI_STATUS Status2;\r
848 EFI_BOOT_MODE BootMode;\r
0c18794e 849\r
c411b485 850 if (!CompareGuid (PcdGetPtr (PcdTpmInstanceGuid), &gEfiTpmDeviceInstanceTpm12Guid)) {\r
e905fbb0 851 DEBUG ((DEBUG_ERROR, "No TPM12 instance required!\n"));\r
c1d93242
JY
852 return EFI_UNSUPPORTED;\r
853 }\r
854\r
3dd05ac3 855 if (GetFirstGuidHob (&gTpmErrorHobGuid) != NULL) {\r
e905fbb0 856 DEBUG ((DEBUG_ERROR, "TPM error!\n"));\r
3dd05ac3
JY
857 return EFI_DEVICE_ERROR;\r
858 }\r
859\r
055c829c 860 //\r
861 // Initialize TPM device\r
862 //\r
863 Status = PeiServicesGetBootMode (&BootMode);\r
864 ASSERT_EFI_ERROR (Status);\r
865\r
866 //\r
867 // In S3 path, skip shadow logic. no measurement is required\r
868 //\r
869 if (BootMode != BOOT_ON_S3_RESUME) {\r
c411b485 870 Status = (**PeiServices).RegisterForShadow (FileHandle);\r
055c829c 871 if (Status == EFI_ALREADY_STARTED) {\r
872 mImageInMemory = TRUE;\r
873 } else if (Status == EFI_NOT_FOUND) {\r
874 ASSERT_EFI_ERROR (Status);\r
875 }\r
0c18794e 876 }\r
877\r
878 if (!mImageInMemory) {\r
b558f8bc 879 Status = Tpm12RequestUseTpm ();\r
0c18794e 880 if (EFI_ERROR (Status)) {\r
881 DEBUG ((DEBUG_ERROR, "TPM not detected!\n"));\r
83a276f6 882 goto Done;\r
0c18794e 883 }\r
884\r
c1d93242 885 if (PcdGet8 (PcdTpmInitializationPolicy) == 1) {\r
45500265
MK
886 if (BootMode == BOOT_ON_S3_RESUME) {\r
887 Status = Tpm12Startup (TPM_ST_STATE);\r
888 } else {\r
889 Status = Tpm12Startup (TPM_ST_CLEAR);\r
890 }\r
c411b485
MK
891\r
892 if (EFI_ERROR (Status)) {\r
83a276f6 893 goto Done;\r
c1d93242 894 }\r
0c18794e 895 }\r
6f6c7857 896\r
897 //\r
898 // TpmSelfTest is optional on S3 path, skip it to save S3 time\r
899 //\r
900 if (BootMode != BOOT_ON_S3_RESUME) {\r
45500265 901 Status = Tpm12ContinueSelfTest ();\r
6f6c7857 902 if (EFI_ERROR (Status)) {\r
83a276f6 903 goto Done;\r
6f6c7857 904 }\r
0c18794e 905 }\r
6f6c7857 906\r
83a276f6 907 //\r
dd40a1f8 908 // Only install TpmInitializedPpi on success\r
83a276f6 909 //\r
0c18794e 910 Status = PeiServicesInstallPpi (&mTpmInitializedPpiList);\r
911 ASSERT_EFI_ERROR (Status);\r
912 }\r
913\r
914 if (mImageInMemory) {\r
c411b485 915 Status = PeimEntryMP ((EFI_PEI_SERVICES **)PeiServices);\r
83a276f6 916 return Status;\r
0c18794e 917 }\r
918\r
83a276f6 919Done:\r
3dd05ac3 920 if (EFI_ERROR (Status)) {\r
e905fbb0 921 DEBUG ((DEBUG_ERROR, "TPM error! Build Hob\n"));\r
c411b485 922 BuildGuidHob (&gTpmErrorHobGuid, 0);\r
3dd05ac3
JY
923 REPORT_STATUS_CODE (\r
924 EFI_ERROR_CODE | EFI_ERROR_MINOR,\r
925 (PcdGet32 (PcdStatusCodeSubClassTpmDevice) | EFI_P_EC_INTERFACE_ERROR)\r
926 );\r
927 }\r
c411b485 928\r
83a276f6 929 //\r
dd40a1f8 930 // Always install TpmInitializationDonePpi no matter success or fail.\r
83a276f6
JY
931 // Other driver can know TPM initialization state by TpmInitializedPpi.\r
932 //\r
933 Status2 = PeiServicesInstallPpi (&mTpmInitializationDonePpiList);\r
934 ASSERT_EFI_ERROR (Status2);\r
935\r
0c18794e 936 return Status;\r
937}\r