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