TcgPei.c 26 KB

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