• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /** @file
2   It updates TPM2 items in ACPI table and registers SMI2 callback
3   functions for Tcg2 physical presence, ClearMemory, and sample
4   for dTPM StartMethod.
5 
6   Caution: This module requires additional review when modified.
7   This driver will have external input - variable and ACPINvs data in SMM mode.
8   This external input must be validated carefully to avoid security issue.
9 
10   PhysicalPresenceCallback() and MemoryClearCallback() will receive untrusted input and do some check.
11 
12 Copyright (c) 2015 - 2017, Intel Corporation. All rights reserved.<BR>
13 This program and the accompanying materials
14 are licensed and made available under the terms and conditions of the BSD License
15 which accompanies this distribution.  The full text of the license may be found at
16 http://opensource.org/licenses/bsd-license.php
17 
18 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
19 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
20 
21 **/
22 
23 #include "Tcg2Smm.h"
24 
25 typedef enum {
26   PtpInterfaceTis,
27   PtpInterfaceFifo,
28   PtpInterfaceCrb,
29   PtpInterfaceMax,
30 } PTP_INTERFACE_TYPE;
31 
32 /**
33   Return PTP interface type.
34 
35   @param[in] Register                Pointer to PTP register.
36 
37   @return PTP interface type.
38 **/
39 PTP_INTERFACE_TYPE
GetPtpInterface(IN VOID * Register)40 GetPtpInterface (
41   IN VOID *Register
42   )
43 {
44   PTP_CRB_INTERFACE_IDENTIFIER  InterfaceId;
45   PTP_FIFO_INTERFACE_CAPABILITY InterfaceCapability;
46 
47   //
48   // Check interface id
49   //
50   InterfaceId.Uint32 = MmioRead32 ((UINTN)&((PTP_CRB_REGISTERS *)Register)->InterfaceId);
51   InterfaceCapability.Uint32 = MmioRead32 ((UINTN)&((PTP_FIFO_REGISTERS *)Register)->InterfaceCapability);
52 
53   if (InterfaceId.Bits.InterfaceType == PTP_INTERFACE_IDENTIFIER_INTERFACE_TYPE_TIS) {
54     return PtpInterfaceTis;
55   }
56 
57   if ((InterfaceId.Bits.InterfaceType == PTP_INTERFACE_IDENTIFIER_INTERFACE_TYPE_CRB) &&
58       (InterfaceId.Bits.InterfaceVersion == PTP_INTERFACE_IDENTIFIER_INTERFACE_VERSION_CRB) &&
59       (InterfaceId.Bits.CapCRB != 0)) {
60     return PtpInterfaceCrb;
61   }
62 
63   if ((InterfaceId.Bits.InterfaceType == PTP_INTERFACE_IDENTIFIER_INTERFACE_TYPE_FIFO) &&
64       (InterfaceId.Bits.InterfaceVersion == PTP_INTERFACE_IDENTIFIER_INTERFACE_VERSION_FIFO) &&
65       (InterfaceId.Bits.CapFIFO != 0) &&
66       (InterfaceCapability.Bits.InterfaceVersion == INTERFACE_CAPABILITY_INTERFACE_VERSION_PTP)) {
67     return PtpInterfaceFifo;
68   }
69 
70   //
71   // No Ptp interface available
72   //
73   return PtpInterfaceMax;
74 }
75 
76 EFI_TPM2_ACPI_TABLE  mTpm2AcpiTemplate = {
77   {
78     EFI_ACPI_5_0_TRUSTED_COMPUTING_PLATFORM_2_TABLE_SIGNATURE,
79     sizeof (mTpm2AcpiTemplate),
80     EFI_TPM2_ACPI_TABLE_REVISION,
81     //
82     // Compiler initializes the remaining bytes to 0
83     // These fields should be filled in in production
84     //
85   },
86   0, // Flags
87   0, // Control Area
88   EFI_TPM2_ACPI_TABLE_START_METHOD_TIS, // StartMethod
89 };
90 
91 EFI_SMM_VARIABLE_PROTOCOL  *mSmmVariable;
92 TCG_NVS                    *mTcgNvs;
93 
94 /**
95   Software SMI callback for TPM physical presence which is called from ACPI method.
96 
97   Caution: This function may receive untrusted input.
98   Variable and ACPINvs are external input, so this function will validate
99   its data structure to be valid value.
100 
101   @param[in]      DispatchHandle  The unique handle assigned to this handler by SmiHandlerRegister().
102   @param[in]      Context         Points to an optional handler context which was specified when the
103                                   handler was registered.
104   @param[in, out] CommBuffer      A pointer to a collection of data in memory that will
105                                   be conveyed from a non-SMM environment into an SMM environment.
106   @param[in, out] CommBufferSize  The size of the CommBuffer.
107 
108   @retval EFI_SUCCESS             The interrupt was handled successfully.
109 
110 **/
111 EFI_STATUS
112 EFIAPI
PhysicalPresenceCallback(IN EFI_HANDLE DispatchHandle,IN CONST VOID * Context,IN OUT VOID * CommBuffer,IN OUT UINTN * CommBufferSize)113 PhysicalPresenceCallback (
114   IN EFI_HANDLE                  DispatchHandle,
115   IN CONST VOID                  *Context,
116   IN OUT VOID                    *CommBuffer,
117   IN OUT UINTN                   *CommBufferSize
118   )
119 {
120   UINT32                MostRecentRequest;
121   UINT32                Response;
122   UINT32                OperationRequest;
123   UINT32                RequestParameter;
124 
125 
126   if (mTcgNvs->PhysicalPresence.Parameter == TCG_ACPI_FUNCTION_RETURN_REQUEST_RESPONSE_TO_OS) {
127     mTcgNvs->PhysicalPresence.ReturnCode = Tcg2PhysicalPresenceLibReturnOperationResponseToOsFunction (
128                                              &MostRecentRequest,
129                                              &Response
130                                              );
131     mTcgNvs->PhysicalPresence.LastRequest = MostRecentRequest;
132     mTcgNvs->PhysicalPresence.Response = Response;
133     return EFI_SUCCESS;
134   } else if ((mTcgNvs->PhysicalPresence.Parameter == TCG_ACPI_FUNCTION_SUBMIT_REQUEST_TO_BIOS)
135           || (mTcgNvs->PhysicalPresence.Parameter == TCG_ACPI_FUNCTION_SUBMIT_REQUEST_TO_BIOS_2)) {
136 
137     OperationRequest = mTcgNvs->PhysicalPresence.Request;
138     RequestParameter = mTcgNvs->PhysicalPresence.RequestParameter;
139     mTcgNvs->PhysicalPresence.ReturnCode = Tcg2PhysicalPresenceLibSubmitRequestToPreOSFunctionEx (
140                                              &OperationRequest,
141                                              &RequestParameter
142                                              );
143     mTcgNvs->PhysicalPresence.Request = OperationRequest;
144     mTcgNvs->PhysicalPresence.RequestParameter = RequestParameter;
145   } else if (mTcgNvs->PhysicalPresence.Parameter == TCG_ACPI_FUNCTION_GET_USER_CONFIRMATION_STATUS_FOR_REQUEST) {
146     mTcgNvs->PhysicalPresence.ReturnCode = Tcg2PhysicalPresenceLibGetUserConfirmationStatusFunction (mTcgNvs->PPRequestUserConfirm);
147   }
148 
149   return EFI_SUCCESS;
150 }
151 
152 
153 /**
154   Software SMI callback for MemoryClear which is called from ACPI method.
155 
156   Caution: This function may receive untrusted input.
157   Variable and ACPINvs are external input, so this function will validate
158   its data structure to be valid value.
159 
160   @param[in]      DispatchHandle  The unique handle assigned to this handler by SmiHandlerRegister().
161   @param[in]      Context         Points to an optional handler context which was specified when the
162                                   handler was registered.
163   @param[in, out] CommBuffer      A pointer to a collection of data in memory that will
164                                   be conveyed from a non-SMM environment into an SMM environment.
165   @param[in, out] CommBufferSize  The size of the CommBuffer.
166 
167   @retval EFI_SUCCESS             The interrupt was handled successfully.
168 
169 **/
170 EFI_STATUS
171 EFIAPI
MemoryClearCallback(IN EFI_HANDLE DispatchHandle,IN CONST VOID * Context,IN OUT VOID * CommBuffer,IN OUT UINTN * CommBufferSize)172 MemoryClearCallback (
173   IN EFI_HANDLE                  DispatchHandle,
174   IN CONST VOID                  *Context,
175   IN OUT VOID                    *CommBuffer,
176   IN OUT UINTN                   *CommBufferSize
177   )
178 {
179   EFI_STATUS                     Status;
180   UINTN                          DataSize;
181   UINT8                          MorControl;
182 
183   mTcgNvs->MemoryClear.ReturnCode = MOR_REQUEST_SUCCESS;
184   if (mTcgNvs->MemoryClear.Parameter == ACPI_FUNCTION_DSM_MEMORY_CLEAR_INTERFACE) {
185     MorControl = (UINT8) mTcgNvs->MemoryClear.Request;
186   } else if (mTcgNvs->MemoryClear.Parameter == ACPI_FUNCTION_PTS_CLEAR_MOR_BIT) {
187     DataSize = sizeof (UINT8);
188     Status = mSmmVariable->SmmGetVariable (
189                              MEMORY_OVERWRITE_REQUEST_VARIABLE_NAME,
190                              &gEfiMemoryOverwriteControlDataGuid,
191                              NULL,
192                              &DataSize,
193                              &MorControl
194                              );
195     if (EFI_ERROR (Status)) {
196       mTcgNvs->MemoryClear.ReturnCode = MOR_REQUEST_GENERAL_FAILURE;
197       DEBUG ((EFI_D_ERROR, "[TPM] Get MOR variable failure! Status = %r\n", Status));
198       return EFI_SUCCESS;
199     }
200 
201     if (MOR_CLEAR_MEMORY_VALUE (MorControl) == 0x0) {
202       return EFI_SUCCESS;
203     }
204     MorControl &= ~MOR_CLEAR_MEMORY_BIT_MASK;
205   }
206 
207   DataSize = sizeof (UINT8);
208   Status = mSmmVariable->SmmSetVariable (
209                            MEMORY_OVERWRITE_REQUEST_VARIABLE_NAME,
210                            &gEfiMemoryOverwriteControlDataGuid,
211                            EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
212                            DataSize,
213                            &MorControl
214                            );
215   if (EFI_ERROR (Status)) {
216     mTcgNvs->MemoryClear.ReturnCode = MOR_REQUEST_GENERAL_FAILURE;
217     DEBUG ((EFI_D_ERROR, "[TPM] Set MOR variable failure! Status = %r\n", Status));
218   }
219 
220   return EFI_SUCCESS;
221 }
222 
223 /**
224   Find the operation region in TCG ACPI table by given Name and Size,
225   and initialize it if the region is found.
226 
227   @param[in, out] Table          The TPM item in ACPI table.
228   @param[in]      Name           The name string to find in TPM table.
229   @param[in]      Size           The size of the region to find.
230 
231   @return                        The allocated address for the found region.
232 
233 **/
234 VOID *
AssignOpRegion(EFI_ACPI_DESCRIPTION_HEADER * Table,UINT32 Name,UINT16 Size)235 AssignOpRegion (
236   EFI_ACPI_DESCRIPTION_HEADER    *Table,
237   UINT32                         Name,
238   UINT16                         Size
239   )
240 {
241   EFI_STATUS                     Status;
242   AML_OP_REGION_32_8             *OpRegion;
243   EFI_PHYSICAL_ADDRESS           MemoryAddress;
244 
245   MemoryAddress = SIZE_4GB - 1;
246 
247   //
248   // Patch some pointers for the ASL code before loading the SSDT.
249   //
250   for (OpRegion  = (AML_OP_REGION_32_8 *) (Table + 1);
251        OpRegion <= (AML_OP_REGION_32_8 *) ((UINT8 *) Table + Table->Length);
252        OpRegion  = (AML_OP_REGION_32_8 *) ((UINT8 *) OpRegion + 1)) {
253     if ((OpRegion->OpRegionOp  == AML_EXT_REGION_OP) &&
254         (OpRegion->NameString  == Name) &&
255         (OpRegion->DWordPrefix == AML_DWORD_PREFIX) &&
256         (OpRegion->BytePrefix  == AML_BYTE_PREFIX)) {
257 
258       Status = gBS->AllocatePages(AllocateMaxAddress, EfiACPIMemoryNVS, EFI_SIZE_TO_PAGES (Size), &MemoryAddress);
259       ASSERT_EFI_ERROR (Status);
260       ZeroMem ((VOID *)(UINTN)MemoryAddress, Size);
261       OpRegion->RegionOffset = (UINT32) (UINTN) MemoryAddress;
262       OpRegion->RegionLen    = (UINT8) Size;
263       break;
264     }
265   }
266 
267   return (VOID *) (UINTN) MemoryAddress;
268 }
269 
270 /**
271   Patch version string of Physical Presence interface supported by platform. The initial string tag in TPM
272 ACPI table is "$PV".
273 
274   @param[in, out] Table          The TPM item in ACPI table.
275   @param[in]      PPVer          Version string of Physical Presence interface supported by platform.
276 
277   @return                        The allocated address for the found region.
278 
279 **/
280 EFI_STATUS
UpdatePPVersion(EFI_ACPI_DESCRIPTION_HEADER * Table,CHAR8 * PPVer)281 UpdatePPVersion (
282   EFI_ACPI_DESCRIPTION_HEADER    *Table,
283   CHAR8                          *PPVer
284   )
285 {
286   EFI_STATUS  Status;
287   UINT8       *DataPtr;
288 
289   //
290   // Patch some pointers for the ASL code before loading the SSDT.
291   //
292   for (DataPtr  = (UINT8 *)(Table + 1);
293        DataPtr <= (UINT8 *) ((UINT8 *) Table + Table->Length - PHYSICAL_PRESENCE_VERSION_SIZE);
294        DataPtr += 1) {
295     if (AsciiStrCmp((CHAR8 *)DataPtr,  PHYSICAL_PRESENCE_VERSION_TAG) == 0) {
296       Status = AsciiStrCpyS((CHAR8 *)DataPtr, PHYSICAL_PRESENCE_VERSION_SIZE, PPVer);
297       DEBUG((EFI_D_INFO, "TPM2 Physical Presence Interface Version update status 0x%x\n", Status));
298       return Status;
299     }
300   }
301 
302   return EFI_NOT_FOUND;
303 }
304 
305 /**
306   Patch TPM2 device HID string.  The initial string tag in TPM2 ACPI table is "NNN0000".
307 
308   @param[in, out] Table          The TPM2 SSDT ACPI table.
309 
310   @return                               HID Update status.
311 
312 **/
313 EFI_STATUS
UpdateHID(EFI_ACPI_DESCRIPTION_HEADER * Table)314 UpdateHID (
315   EFI_ACPI_DESCRIPTION_HEADER    *Table
316   )
317 {
318   EFI_STATUS  Status;
319   UINT8       *DataPtr;
320   CHAR8       Hid[TPM_HID_ACPI_SIZE];
321   UINT32      ManufacturerID;
322   UINT32      FirmwareVersion1;
323   UINT32      FirmwareVersion2;
324   BOOLEAN     PnpHID;
325 
326   PnpHID = TRUE;
327 
328   //
329   // Initialize HID with Default PNP string
330   //
331   ZeroMem(Hid, TPM_HID_ACPI_SIZE);
332 
333   //
334   // Get Manufacturer ID
335   //
336   Status = Tpm2GetCapabilityManufactureID(&ManufacturerID);
337   if (!EFI_ERROR(Status)) {
338     DEBUG((EFI_D_INFO, "TPM_PT_MANUFACTURER 0x%08x\n", ManufacturerID));
339     //
340     // ManufacturerID defined in TCG Vendor ID Registry
341     // may tailed with 0x00 or 0x20
342     //
343     if ((ManufacturerID >> 24) == 0x00 || ((ManufacturerID >> 24) == 0x20)) {
344       //
345       //  HID containing PNP ID "NNN####"
346       //   NNN is uppercase letter for Vendor ID specified by manufacturer
347       //
348       CopyMem(Hid, &ManufacturerID, 3);
349     } else {
350       //
351       //  HID containing ACP ID "NNNN####"
352       //   NNNN is uppercase letter for Vendor ID specified by manufacturer
353       //
354       CopyMem(Hid, &ManufacturerID, 4);
355       PnpHID = FALSE;
356     }
357   } else {
358     DEBUG ((EFI_D_ERROR, "Get TPM_PT_MANUFACTURER failed %x!\n", Status));
359     ASSERT(FALSE);
360     return Status;
361   }
362 
363   Status = Tpm2GetCapabilityFirmwareVersion(&FirmwareVersion1, &FirmwareVersion2);
364   if (!EFI_ERROR(Status)) {
365     DEBUG((EFI_D_INFO, "TPM_PT_FIRMWARE_VERSION_1 0x%x\n", FirmwareVersion1));
366     DEBUG((EFI_D_INFO, "TPM_PT_FIRMWARE_VERSION_2 0x%x\n", FirmwareVersion2));
367     //
368     //   #### is Firmware Version 1
369     //
370     if (PnpHID) {
371       AsciiSPrint(Hid + 3, TPM_HID_PNP_SIZE - 3, "%02d%02d", ((FirmwareVersion1 & 0xFFFF0000) >> 16), (FirmwareVersion1 && 0x0000FFFF));
372     } else {
373       AsciiSPrint(Hid + 4, TPM_HID_ACPI_SIZE - 4, "%02d%02d", ((FirmwareVersion1 & 0xFFFF0000) >> 16), (FirmwareVersion1 && 0x0000FFFF));
374     }
375 
376   } else {
377     DEBUG ((EFI_D_ERROR, "Get TPM_PT_FIRMWARE_VERSION_X failed %x!\n", Status));
378     ASSERT(FALSE);
379     return Status;
380   }
381 
382   //
383   // Patch HID in ASL code before loading the SSDT.
384   //
385   for (DataPtr  = (UINT8 *)(Table + 1);
386        DataPtr <= (UINT8 *) ((UINT8 *) Table + Table->Length - TPM_HID_PNP_SIZE);
387        DataPtr += 1) {
388     if (AsciiStrCmp((CHAR8 *)DataPtr,  TPM_HID_TAG) == 0) {
389       if (PnpHID) {
390         CopyMem(DataPtr, Hid, TPM_HID_PNP_SIZE);
391         //
392         // if HID is PNP ID, patch the last byte in HID TAG to Noop
393         //
394         *(DataPtr + TPM_HID_PNP_SIZE) = AML_NOOP_OP;
395       } else {
396 
397         CopyMem(DataPtr, Hid, TPM_HID_ACPI_SIZE);
398       }
399       DEBUG((DEBUG_INFO, "TPM2 ACPI _HID is patched to %a\n", DataPtr));
400 
401       return Status;
402     }
403   }
404 
405   DEBUG((EFI_D_ERROR, "TPM2 ACPI HID TAG for patch not found!\n"));
406   return EFI_NOT_FOUND;
407 }
408 
409 /**
410   Initialize and publish TPM items in ACPI table.
411 
412   @retval   EFI_SUCCESS     The TCG ACPI table is published successfully.
413   @retval   Others          The TCG ACPI table is not published.
414 
415 **/
416 EFI_STATUS
PublishAcpiTable(VOID)417 PublishAcpiTable (
418   VOID
419   )
420 {
421   EFI_STATUS                     Status;
422   EFI_ACPI_TABLE_PROTOCOL        *AcpiTable;
423   UINTN                          TableKey;
424   EFI_ACPI_DESCRIPTION_HEADER    *Table;
425   UINTN                          TableSize;
426 
427   Status = GetSectionFromFv (
428              &gEfiCallerIdGuid,
429              EFI_SECTION_RAW,
430              0,
431              (VOID **) &Table,
432              &TableSize
433              );
434   ASSERT_EFI_ERROR (Status);
435 
436   //
437   // Update Table version before measuring it to PCR
438   //
439   Status = UpdatePPVersion(Table, (CHAR8 *)PcdGetPtr(PcdTcgPhysicalPresenceInterfaceVer));
440   ASSERT_EFI_ERROR (Status);
441 
442   //
443   // Update TPM2 HID before measuring it to PCR
444   //
445   Status = UpdateHID(Table);
446   if (EFI_ERROR(Status)) {
447     return Status;
448   }
449 
450   //
451   // Measure to PCR[0] with event EV_POST_CODE ACPI DATA
452   //
453   TpmMeasureAndLogData(
454     0,
455     EV_POST_CODE,
456     EV_POSTCODE_INFO_ACPI_DATA,
457     ACPI_DATA_LEN,
458     Table,
459     TableSize
460     );
461 
462 
463   ASSERT (Table->OemTableId == SIGNATURE_64 ('T', 'p', 'm', '2', 'T', 'a', 'b', 'l'));
464   CopyMem (Table->OemId, PcdGetPtr (PcdAcpiDefaultOemId), sizeof (Table->OemId) );
465   mTcgNvs = AssignOpRegion (Table, SIGNATURE_32 ('T', 'N', 'V', 'S'), (UINT16) sizeof (TCG_NVS));
466   ASSERT (mTcgNvs != NULL);
467 
468   //
469   // Publish the TPM ACPI table. Table is re-checksumed.
470   //
471   Status = gBS->LocateProtocol (&gEfiAcpiTableProtocolGuid, NULL, (VOID **) &AcpiTable);
472   ASSERT_EFI_ERROR (Status);
473 
474   TableKey = 0;
475   Status = AcpiTable->InstallAcpiTable (
476                         AcpiTable,
477                         Table,
478                         TableSize,
479                         &TableKey
480                         );
481   ASSERT_EFI_ERROR (Status);
482 
483   return Status;
484 }
485 
486 /**
487   Publish TPM2 ACPI table
488 
489   @retval   EFI_SUCCESS     The TPM2 ACPI table is published successfully.
490   @retval   Others          The TPM2 ACPI table is not published.
491 
492 **/
493 EFI_STATUS
PublishTpm2(VOID)494 PublishTpm2 (
495   VOID
496   )
497 {
498   EFI_STATUS                     Status;
499   EFI_ACPI_TABLE_PROTOCOL        *AcpiTable;
500   UINTN                          TableKey;
501   UINT64                         OemTableId;
502   EFI_TPM2_ACPI_CONTROL_AREA     *ControlArea;
503   PTP_INTERFACE_TYPE             InterfaceType;
504 
505   //
506   // Measure to PCR[0] with event EV_POST_CODE ACPI DATA
507   //
508   TpmMeasureAndLogData(
509     0,
510     EV_POST_CODE,
511     EV_POSTCODE_INFO_ACPI_DATA,
512     ACPI_DATA_LEN,
513     &mTpm2AcpiTemplate,
514     sizeof(mTpm2AcpiTemplate)
515     );
516 
517   InterfaceType = GetPtpInterface ((VOID *) (UINTN) PcdGet64 (PcdTpmBaseAddress));
518   switch (InterfaceType) {
519   case PtpInterfaceCrb:
520     mTpm2AcpiTemplate.StartMethod = EFI_TPM2_ACPI_TABLE_START_METHOD_COMMAND_RESPONSE_BUFFER_INTERFACE;
521     mTpm2AcpiTemplate.AddressOfControlArea = PcdGet64 (PcdTpmBaseAddress) + 0x40;
522     ControlArea = (EFI_TPM2_ACPI_CONTROL_AREA *)(UINTN)mTpm2AcpiTemplate.AddressOfControlArea;
523     ControlArea->CommandSize  = 0xF80;
524     ControlArea->ResponseSize = 0xF80;
525     ControlArea->Command      = PcdGet64 (PcdTpmBaseAddress) + 0x80;
526     ControlArea->Response     = PcdGet64 (PcdTpmBaseAddress) + 0x80;
527     break;
528   case PtpInterfaceFifo:
529   case PtpInterfaceTis:
530     break;
531   default:
532     DEBUG((EFI_D_ERROR, "TPM2 InterfaceType get error! %d\n", InterfaceType));
533     break;
534   }
535 
536   CopyMem (mTpm2AcpiTemplate.Header.OemId, PcdGetPtr (PcdAcpiDefaultOemId), sizeof (mTpm2AcpiTemplate.Header.OemId));
537   OemTableId = PcdGet64 (PcdAcpiDefaultOemTableId);
538   CopyMem (&mTpm2AcpiTemplate.Header.OemTableId, &OemTableId, sizeof (UINT64));
539   mTpm2AcpiTemplate.Header.OemRevision      = PcdGet32 (PcdAcpiDefaultOemRevision);
540   mTpm2AcpiTemplate.Header.CreatorId        = PcdGet32 (PcdAcpiDefaultCreatorId);
541   mTpm2AcpiTemplate.Header.CreatorRevision  = PcdGet32 (PcdAcpiDefaultCreatorRevision);
542 
543   //
544   // Construct ACPI table
545   //
546   Status = gBS->LocateProtocol (&gEfiAcpiTableProtocolGuid, NULL, (VOID **) &AcpiTable);
547   ASSERT_EFI_ERROR (Status);
548 
549   Status = AcpiTable->InstallAcpiTable (
550                         AcpiTable,
551                         &mTpm2AcpiTemplate,
552                         sizeof(mTpm2AcpiTemplate),
553                         &TableKey
554                         );
555   ASSERT_EFI_ERROR (Status);
556 
557   return Status;
558 }
559 
560 /**
561   The driver's entry point.
562 
563   It install callbacks for TPM physical presence and MemoryClear, and locate
564   SMM variable to be used in the callback function.
565 
566   @param[in] ImageHandle  The firmware allocated handle for the EFI image.
567   @param[in] SystemTable  A pointer to the EFI System Table.
568 
569   @retval EFI_SUCCESS     The entry point is executed successfully.
570   @retval Others          Some error occurs when executing this entry point.
571 
572 **/
573 EFI_STATUS
574 EFIAPI
InitializeTcgSmm(IN EFI_HANDLE ImageHandle,IN EFI_SYSTEM_TABLE * SystemTable)575 InitializeTcgSmm (
576   IN EFI_HANDLE                  ImageHandle,
577   IN EFI_SYSTEM_TABLE            *SystemTable
578   )
579 {
580   EFI_STATUS                     Status;
581   EFI_SMM_SW_DISPATCH2_PROTOCOL  *SwDispatch;
582   EFI_SMM_SW_REGISTER_CONTEXT    SwContext;
583   EFI_HANDLE                     SwHandle;
584 
585   if (!CompareGuid (PcdGetPtr(PcdTpmInstanceGuid), &gEfiTpmDeviceInstanceTpm20DtpmGuid)){
586     DEBUG ((EFI_D_ERROR, "No TPM2 DTPM instance required!\n"));
587     return EFI_UNSUPPORTED;
588   }
589 
590   Status = PublishAcpiTable ();
591   ASSERT_EFI_ERROR (Status);
592 
593   //
594   // Get the Sw dispatch protocol and register SMI callback functions.
595   //
596   Status = gSmst->SmmLocateProtocol (&gEfiSmmSwDispatch2ProtocolGuid, NULL, (VOID**)&SwDispatch);
597   ASSERT_EFI_ERROR (Status);
598   SwContext.SwSmiInputValue = (UINTN) -1;
599   Status = SwDispatch->Register (SwDispatch, PhysicalPresenceCallback, &SwContext, &SwHandle);
600   ASSERT_EFI_ERROR (Status);
601   if (EFI_ERROR (Status)) {
602     return Status;
603   }
604   mTcgNvs->PhysicalPresence.SoftwareSmi = (UINT8) SwContext.SwSmiInputValue;
605 
606   SwContext.SwSmiInputValue = (UINTN) -1;
607   Status = SwDispatch->Register (SwDispatch, MemoryClearCallback, &SwContext, &SwHandle);
608   ASSERT_EFI_ERROR (Status);
609   if (EFI_ERROR (Status)) {
610     return Status;
611   }
612   mTcgNvs->MemoryClear.SoftwareSmi = (UINT8) SwContext.SwSmiInputValue;
613 
614   //
615   // Locate SmmVariableProtocol.
616   //
617   Status = gSmst->SmmLocateProtocol (&gEfiSmmVariableProtocolGuid, NULL, (VOID**)&mSmmVariable);
618   ASSERT_EFI_ERROR (Status);
619 
620   //
621   // Set TPM2 ACPI table
622   //
623   Status = PublishTpm2 ();
624   ASSERT_EFI_ERROR (Status);
625 
626 
627   return EFI_SUCCESS;
628 }
629 
630