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