1 /** @file
2   It updates TPM2 items in ACPI table and registers SMI2 callback
3   functions for TrEE 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) 2013 - 2015, 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 "TrEESmm.h"
24 
25 EFI_TPM2_ACPI_TABLE  mTpm2AcpiTemplate = {
26   {
27     EFI_ACPI_5_0_TRUSTED_COMPUTING_PLATFORM_2_TABLE_SIGNATURE,
28     sizeof (mTpm2AcpiTemplate),
29     EFI_TPM2_ACPI_TABLE_REVISION,
30     //
31     // Compiler initializes the remaining bytes to 0
32     // These fields should be filled in in production
33     //
34   },
35   0, // Flags
36   0, // Control Area
37   EFI_TPM2_ACPI_TABLE_START_METHOD_TIS, // StartMethod
38 };
39 
40 EFI_SMM_VARIABLE_PROTOCOL  *mSmmVariable;
41 TCG_NVS                    *mTcgNvs;
42 
43 /**
44   Software SMI callback for TPM physical presence which is called from ACPI method.
45 
46   Caution: This function may receive untrusted input.
47   Variable and ACPINvs are external input, so this function will validate
48   its data structure to be valid value.
49 
50   @param[in]      DispatchHandle  The unique handle assigned to this handler by SmiHandlerRegister().
51   @param[in]      Context         Points to an optional handler context which was specified when the
52                                   handler was registered.
53   @param[in, out] CommBuffer      A pointer to a collection of data in memory that will
54                                   be conveyed from a non-SMM environment into an SMM environment.
55   @param[in, out] CommBufferSize  The size of the CommBuffer.
56 
57   @retval EFI_SUCCESS             The interrupt was handled successfully.
58 
59 **/
60 EFI_STATUS
61 EFIAPI
PhysicalPresenceCallback(IN EFI_HANDLE DispatchHandle,IN CONST VOID * Context,IN OUT VOID * CommBuffer,IN OUT UINTN * CommBufferSize)62 PhysicalPresenceCallback (
63   IN EFI_HANDLE                  DispatchHandle,
64   IN CONST VOID                  *Context,
65   IN OUT VOID                    *CommBuffer,
66   IN OUT UINTN                   *CommBufferSize
67   )
68 {
69   EFI_STATUS                        Status;
70   UINTN                             DataSize;
71   EFI_TREE_PHYSICAL_PRESENCE        PpData;
72   EFI_TREE_PHYSICAL_PRESENCE_FLAGS  Flags;
73   BOOLEAN                           RequestConfirmed;
74 
75   //
76   // Get the Physical Presence variable
77   //
78   DataSize = sizeof (EFI_TREE_PHYSICAL_PRESENCE);
79   Status = mSmmVariable->SmmGetVariable (
80                            TREE_PHYSICAL_PRESENCE_VARIABLE,
81                            &gEfiTrEEPhysicalPresenceGuid,
82                            NULL,
83                            &DataSize,
84                            &PpData
85                            );
86 
87   DEBUG ((EFI_D_INFO, "[TPM2] PP callback, Parameter = %x, Request = %x\n", mTcgNvs->PhysicalPresence.Parameter, mTcgNvs->PhysicalPresence.Request));
88 
89   if (mTcgNvs->PhysicalPresence.Parameter == ACPI_FUNCTION_RETURN_REQUEST_RESPONSE_TO_OS) {
90     if (EFI_ERROR (Status)) {
91       mTcgNvs->PhysicalPresence.ReturnCode  = PP_RETURN_TPM_OPERATION_RESPONSE_FAILURE;
92       mTcgNvs->PhysicalPresence.LastRequest = 0;
93       mTcgNvs->PhysicalPresence.Response    = 0;
94       DEBUG ((EFI_D_ERROR, "[TPM2] Get PP variable failure! Status = %r\n", Status));
95       return EFI_SUCCESS;
96     }
97     mTcgNvs->PhysicalPresence.ReturnCode  = PP_RETURN_TPM_OPERATION_RESPONSE_SUCCESS;
98     mTcgNvs->PhysicalPresence.LastRequest = PpData.LastPPRequest;
99     mTcgNvs->PhysicalPresence.Response    = PpData.PPResponse;
100   } else if ((mTcgNvs->PhysicalPresence.Parameter == ACPI_FUNCTION_SUBMIT_REQUEST_TO_BIOS)
101           || (mTcgNvs->PhysicalPresence.Parameter == ACPI_FUNCTION_SUBMIT_REQUEST_TO_BIOS_2)) {
102     if (EFI_ERROR (Status)) {
103       mTcgNvs->PhysicalPresence.ReturnCode = TREE_PP_SUBMIT_REQUEST_TO_PREOS_GENERAL_FAILURE;
104       DEBUG ((EFI_D_ERROR, "[TPM2] Get PP variable failure! Status = %r\n", Status));
105       return EFI_SUCCESS;
106     }
107     if ((mTcgNvs->PhysicalPresence.Request > TREE_PHYSICAL_PRESENCE_NO_ACTION_MAX) &&
108         (mTcgNvs->PhysicalPresence.Request < TREE_PHYSICAL_PRESENCE_VENDOR_SPECIFIC_OPERATION) ) {
109       //
110       // This command requires UI to prompt user for Auth data.
111       //
112       mTcgNvs->PhysicalPresence.ReturnCode = TREE_PP_SUBMIT_REQUEST_TO_PREOS_NOT_IMPLEMENTED;
113       return EFI_SUCCESS;
114     }
115 
116     if (PpData.PPRequest != mTcgNvs->PhysicalPresence.Request) {
117       PpData.PPRequest = (UINT8) mTcgNvs->PhysicalPresence.Request;
118       DataSize = sizeof (EFI_TREE_PHYSICAL_PRESENCE);
119       Status = mSmmVariable->SmmSetVariable (
120                                TREE_PHYSICAL_PRESENCE_VARIABLE,
121                                &gEfiTrEEPhysicalPresenceGuid,
122                                EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
123                                DataSize,
124                                &PpData
125                                );
126     }
127 
128     if (EFI_ERROR (Status)) {
129       mTcgNvs->PhysicalPresence.ReturnCode = TREE_PP_SUBMIT_REQUEST_TO_PREOS_GENERAL_FAILURE;
130       DEBUG ((EFI_D_ERROR, "[TPM2] Set PP variable failure! Status = %r\n", Status));
131       return EFI_SUCCESS;
132     }
133     mTcgNvs->PhysicalPresence.ReturnCode = TREE_PP_SUBMIT_REQUEST_TO_PREOS_SUCCESS;
134 
135     if (mTcgNvs->PhysicalPresence.Request >= TREE_PHYSICAL_PRESENCE_VENDOR_SPECIFIC_OPERATION) {
136       DataSize = sizeof (EFI_TREE_PHYSICAL_PRESENCE_FLAGS);
137       Status = mSmmVariable->SmmGetVariable (
138                                TREE_PHYSICAL_PRESENCE_FLAGS_VARIABLE,
139                                &gEfiTrEEPhysicalPresenceGuid,
140                                NULL,
141                                &DataSize,
142                                &Flags
143                                );
144       if (EFI_ERROR (Status)) {
145         Flags.PPFlags = 0;
146       }
147       mTcgNvs->PhysicalPresence.ReturnCode = TrEEPpVendorLibSubmitRequestToPreOSFunction (mTcgNvs->PhysicalPresence.Request, Flags.PPFlags);
148     }
149   } else if (mTcgNvs->PhysicalPresence.Parameter == ACPI_FUNCTION_GET_USER_CONFIRMATION_STATUS_FOR_REQUEST) {
150     if (EFI_ERROR (Status)) {
151       mTcgNvs->PhysicalPresence.ReturnCode = TREE_PP_GET_USER_CONFIRMATION_BLOCKED_BY_BIOS_CONFIGURATION;
152       DEBUG ((EFI_D_ERROR, "[TPM2] Get PP variable failure! Status = %r\n", Status));
153       return EFI_SUCCESS;
154     }
155     //
156     // Get the Physical Presence flags
157     //
158     DataSize = sizeof (EFI_TREE_PHYSICAL_PRESENCE_FLAGS);
159     Status = mSmmVariable->SmmGetVariable (
160                              TREE_PHYSICAL_PRESENCE_FLAGS_VARIABLE,
161                              &gEfiTrEEPhysicalPresenceGuid,
162                              NULL,
163                              &DataSize,
164                              &Flags
165                              );
166     if (EFI_ERROR (Status)) {
167       mTcgNvs->PhysicalPresence.ReturnCode = TREE_PP_GET_USER_CONFIRMATION_BLOCKED_BY_BIOS_CONFIGURATION;
168       DEBUG ((EFI_D_ERROR, "[TPM2] Get PP flags failure! Status = %r\n", Status));
169       return EFI_SUCCESS;
170     }
171 
172     RequestConfirmed = FALSE;
173 
174     switch (mTcgNvs->PhysicalPresence.Request) {
175 
176       case TREE_PHYSICAL_PRESENCE_CLEAR_CONTROL_CLEAR:
177       case TREE_PHYSICAL_PRESENCE_CLEAR_CONTROL_CLEAR_2:
178       case TREE_PHYSICAL_PRESENCE_CLEAR_CONTROL_CLEAR_3:
179       case TREE_PHYSICAL_PRESENCE_CLEAR_CONTROL_CLEAR_4:
180         if ((Flags.PPFlags & TREE_BIOS_TPM_MANAGEMENT_FLAG_NO_PPI_CLEAR) != 0) {
181           RequestConfirmed = TRUE;
182         }
183         break;
184 
185       case TREE_PHYSICAL_PRESENCE_SET_NO_PPI_CLEAR_FALSE:
186         RequestConfirmed = TRUE;
187         break;
188 
189       case TREE_PHYSICAL_PRESENCE_SET_NO_PPI_CLEAR_TRUE:
190         break;
191 
192       default:
193         if (mTcgNvs->PhysicalPresence.Request <= TREE_PHYSICAL_PRESENCE_NO_ACTION_MAX) {
194           RequestConfirmed = TRUE;
195         } else {
196           if (mTcgNvs->PhysicalPresence.Request < TREE_PHYSICAL_PRESENCE_VENDOR_SPECIFIC_OPERATION) {
197             mTcgNvs->PhysicalPresence.ReturnCode = TREE_PP_GET_USER_CONFIRMATION_NOT_IMPLEMENTED;
198             return EFI_SUCCESS;
199           }
200         }
201         break;
202     }
203 
204     if (RequestConfirmed) {
205       mTcgNvs->PhysicalPresence.ReturnCode = TREE_PP_GET_USER_CONFIRMATION_ALLOWED_AND_PPUSER_NOT_REQUIRED;
206     } else {
207       mTcgNvs->PhysicalPresence.ReturnCode = TREE_PP_GET_USER_CONFIRMATION_ALLOWED_AND_PPUSER_REQUIRED;
208     }
209     if (mTcgNvs->PhysicalPresence.Request >= TREE_PHYSICAL_PRESENCE_VENDOR_SPECIFIC_OPERATION) {
210       mTcgNvs->PhysicalPresence.ReturnCode = TrEEPpVendorLibGetUserConfirmationStatusFunction (mTcgNvs->PhysicalPresence.Request, Flags.PPFlags);
211     }
212   }
213 
214   return EFI_SUCCESS;
215 }
216 
217 
218 /**
219   Software SMI callback for MemoryClear which is called from ACPI method.
220 
221   Caution: This function may receive untrusted input.
222   Variable and ACPINvs are external input, so this function will validate
223   its data structure to be valid value.
224 
225   @param[in]      DispatchHandle  The unique handle assigned to this handler by SmiHandlerRegister().
226   @param[in]      Context         Points to an optional handler context which was specified when the
227                                   handler was registered.
228   @param[in, out] CommBuffer      A pointer to a collection of data in memory that will
229                                   be conveyed from a non-SMM environment into an SMM environment.
230   @param[in, out] CommBufferSize  The size of the CommBuffer.
231 
232   @retval EFI_SUCCESS             The interrupt was handled successfully.
233 
234 **/
235 EFI_STATUS
236 EFIAPI
MemoryClearCallback(IN EFI_HANDLE DispatchHandle,IN CONST VOID * Context,IN OUT VOID * CommBuffer,IN OUT UINTN * CommBufferSize)237 MemoryClearCallback (
238   IN EFI_HANDLE                  DispatchHandle,
239   IN CONST VOID                  *Context,
240   IN OUT VOID                    *CommBuffer,
241   IN OUT UINTN                   *CommBufferSize
242   )
243 {
244   EFI_STATUS                     Status;
245   UINTN                          DataSize;
246   UINT8                          MorControl;
247 
248   mTcgNvs->MemoryClear.ReturnCode = MOR_REQUEST_SUCCESS;
249   if (mTcgNvs->MemoryClear.Parameter == ACPI_FUNCTION_DSM_MEMORY_CLEAR_INTERFACE) {
250     MorControl = (UINT8) mTcgNvs->MemoryClear.Request;
251   } else if (mTcgNvs->MemoryClear.Parameter == ACPI_FUNCTION_PTS_CLEAR_MOR_BIT) {
252     DataSize = sizeof (UINT8);
253     Status = mSmmVariable->SmmGetVariable (
254                              MEMORY_OVERWRITE_REQUEST_VARIABLE_NAME,
255                              &gEfiMemoryOverwriteControlDataGuid,
256                              NULL,
257                              &DataSize,
258                              &MorControl
259                              );
260     if (EFI_ERROR (Status)) {
261       mTcgNvs->MemoryClear.ReturnCode = MOR_REQUEST_GENERAL_FAILURE;
262       DEBUG ((EFI_D_ERROR, "[TPM] Get MOR variable failure! Status = %r\n", Status));
263       return EFI_SUCCESS;
264     }
265 
266     if (MOR_CLEAR_MEMORY_VALUE (MorControl) == 0x0) {
267       return EFI_SUCCESS;
268     }
269     MorControl &= ~MOR_CLEAR_MEMORY_BIT_MASK;
270   }
271 
272   DataSize = sizeof (UINT8);
273   Status = mSmmVariable->SmmSetVariable (
274                            MEMORY_OVERWRITE_REQUEST_VARIABLE_NAME,
275                            &gEfiMemoryOverwriteControlDataGuid,
276                            EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
277                            DataSize,
278                            &MorControl
279                            );
280   if (EFI_ERROR (Status)) {
281     mTcgNvs->MemoryClear.ReturnCode = MOR_REQUEST_GENERAL_FAILURE;
282     DEBUG ((EFI_D_ERROR, "[TPM] Set MOR variable failure! Status = %r\n", Status));
283   }
284 
285   return EFI_SUCCESS;
286 }
287 
288 /**
289   Find the operation region in TCG ACPI table by given Name and Size,
290   and initialize it if the region is found.
291 
292   @param[in, out] Table          The TPM item in ACPI table.
293   @param[in]      Name           The name string to find in TPM table.
294   @param[in]      Size           The size of the region to find.
295 
296   @return                        The allocated address for the found region.
297 
298 **/
299 VOID *
AssignOpRegion(EFI_ACPI_DESCRIPTION_HEADER * Table,UINT32 Name,UINT16 Size)300 AssignOpRegion (
301   EFI_ACPI_DESCRIPTION_HEADER    *Table,
302   UINT32                         Name,
303   UINT16                         Size
304   )
305 {
306   EFI_STATUS                     Status;
307   AML_OP_REGION_32_8             *OpRegion;
308   EFI_PHYSICAL_ADDRESS           MemoryAddress;
309 
310   MemoryAddress = SIZE_4GB - 1;
311 
312   //
313   // Patch some pointers for the ASL code before loading the SSDT.
314   //
315   for (OpRegion  = (AML_OP_REGION_32_8 *) (Table + 1);
316        OpRegion <= (AML_OP_REGION_32_8 *) ((UINT8 *) Table + Table->Length);
317        OpRegion  = (AML_OP_REGION_32_8 *) ((UINT8 *) OpRegion + 1)) {
318     if ((OpRegion->OpRegionOp  == AML_EXT_REGION_OP) &&
319         (OpRegion->NameString  == Name) &&
320         (OpRegion->DWordPrefix == AML_DWORD_PREFIX) &&
321         (OpRegion->BytePrefix  == AML_BYTE_PREFIX)) {
322 
323       Status = gBS->AllocatePages(AllocateMaxAddress, EfiACPIMemoryNVS, EFI_SIZE_TO_PAGES (Size), &MemoryAddress);
324       ASSERT_EFI_ERROR (Status);
325       ZeroMem ((VOID *)(UINTN)MemoryAddress, Size);
326       OpRegion->RegionOffset = (UINT32) (UINTN) MemoryAddress;
327       OpRegion->RegionLen    = (UINT8) Size;
328       break;
329     }
330   }
331 
332   return (VOID *) (UINTN) MemoryAddress;
333 }
334 
335 /**
336   Initialize and publish TPM items in ACPI table.
337 
338   @retval   EFI_SUCCESS     The TCG ACPI table is published successfully.
339   @retval   Others          The TCG ACPI table is not published.
340 
341 **/
342 EFI_STATUS
PublishAcpiTable(VOID)343 PublishAcpiTable (
344   VOID
345   )
346 {
347   EFI_STATUS                     Status;
348   EFI_ACPI_TABLE_PROTOCOL        *AcpiTable;
349   UINTN                          TableKey;
350   EFI_ACPI_DESCRIPTION_HEADER    *Table;
351   UINTN                          TableSize;
352 
353   Status = GetSectionFromFv (
354              &gEfiCallerIdGuid,
355              EFI_SECTION_RAW,
356              0,
357              (VOID **) &Table,
358              &TableSize
359              );
360   ASSERT_EFI_ERROR (Status);
361 
362 
363   //
364   // Measure to PCR[0] with event EV_POST_CODE ACPI DATA
365   //
366   TpmMeasureAndLogData(
367     0,
368     EV_POST_CODE,
369     EV_POSTCODE_INFO_ACPI_DATA,
370     ACPI_DATA_LEN,
371     Table,
372     TableSize
373     );
374 
375 
376   ASSERT (Table->OemTableId == SIGNATURE_64 ('T', 'p', 'm', '2', 'T', 'a', 'b', 'l'));
377   CopyMem (Table->OemId, PcdGetPtr (PcdAcpiDefaultOemId), sizeof (Table->OemId) );
378   mTcgNvs = AssignOpRegion (Table, SIGNATURE_32 ('T', 'N', 'V', 'S'), (UINT16) sizeof (TCG_NVS));
379   ASSERT (mTcgNvs != NULL);
380 
381   //
382   // Publish the TPM ACPI table
383   //
384   Status = gBS->LocateProtocol (&gEfiAcpiTableProtocolGuid, NULL, (VOID **) &AcpiTable);
385   ASSERT_EFI_ERROR (Status);
386 
387   TableKey = 0;
388   Status = AcpiTable->InstallAcpiTable (
389                         AcpiTable,
390                         Table,
391                         TableSize,
392                         &TableKey
393                         );
394   ASSERT_EFI_ERROR (Status);
395 
396   return Status;
397 }
398 
399 /**
400   Publish TPM2 ACPI table
401 
402   @retval   EFI_SUCCESS     The TPM2 ACPI table is published successfully.
403   @retval   Others          The TPM2 ACPI table is not published.
404 
405 **/
406 EFI_STATUS
PublishTpm2(VOID)407 PublishTpm2 (
408   VOID
409   )
410 {
411   EFI_STATUS                     Status;
412   EFI_ACPI_TABLE_PROTOCOL        *AcpiTable;
413   UINTN                          TableKey;
414   UINT64                         OemTableId;
415 
416   //
417   // Measure to PCR[0] with event EV_POST_CODE ACPI DATA
418   //
419   TpmMeasureAndLogData(
420     0,
421     EV_POST_CODE,
422     EV_POSTCODE_INFO_ACPI_DATA,
423     ACPI_DATA_LEN,
424     &mTpm2AcpiTemplate,
425     sizeof(mTpm2AcpiTemplate)
426     );
427 
428   CopyMem (mTpm2AcpiTemplate.Header.OemId, PcdGetPtr (PcdAcpiDefaultOemId), sizeof (mTpm2AcpiTemplate.Header.OemId));
429   OemTableId = PcdGet64 (PcdAcpiDefaultOemTableId);
430   CopyMem (&mTpm2AcpiTemplate.Header.OemTableId, &OemTableId, sizeof (UINT64));
431   mTpm2AcpiTemplate.Header.OemRevision      = PcdGet32 (PcdAcpiDefaultOemRevision);
432   mTpm2AcpiTemplate.Header.CreatorId        = PcdGet32 (PcdAcpiDefaultCreatorId);
433   mTpm2AcpiTemplate.Header.CreatorRevision  = PcdGet32 (PcdAcpiDefaultCreatorRevision);
434 
435   //
436   // Construct ACPI table
437   //
438   Status = gBS->LocateProtocol (&gEfiAcpiTableProtocolGuid, NULL, (VOID **) &AcpiTable);
439   ASSERT_EFI_ERROR (Status);
440 
441   Status = AcpiTable->InstallAcpiTable (
442                         AcpiTable,
443                         &mTpm2AcpiTemplate,
444                         sizeof(mTpm2AcpiTemplate),
445                         &TableKey
446                         );
447   ASSERT_EFI_ERROR (Status);
448 
449   return Status;
450 }
451 
452 /**
453   The driver's entry point.
454 
455   It install callbacks for TPM physical presence and MemoryClear, and locate
456   SMM variable to be used in the callback function.
457 
458   @param[in] ImageHandle  The firmware allocated handle for the EFI image.
459   @param[in] SystemTable  A pointer to the EFI System Table.
460 
461   @retval EFI_SUCCESS     The entry point is executed successfully.
462   @retval Others          Some error occurs when executing this entry point.
463 
464 **/
465 EFI_STATUS
466 EFIAPI
InitializeTcgSmm(IN EFI_HANDLE ImageHandle,IN EFI_SYSTEM_TABLE * SystemTable)467 InitializeTcgSmm (
468   IN EFI_HANDLE                  ImageHandle,
469   IN EFI_SYSTEM_TABLE            *SystemTable
470   )
471 {
472   EFI_STATUS                     Status;
473   EFI_SMM_SW_DISPATCH2_PROTOCOL  *SwDispatch;
474   EFI_SMM_SW_REGISTER_CONTEXT    SwContext;
475   EFI_HANDLE                     SwHandle;
476 
477   if (!CompareGuid (PcdGetPtr(PcdTpmInstanceGuid), &gEfiTpmDeviceInstanceTpm20DtpmGuid)){
478     DEBUG ((EFI_D_ERROR, "No TPM2 DTPM instance required!\n"));
479     return EFI_UNSUPPORTED;
480   }
481 
482   Status = PublishAcpiTable ();
483   ASSERT_EFI_ERROR (Status);
484 
485   //
486   // Get the Sw dispatch protocol and register SMI callback functions.
487   //
488   Status = gSmst->SmmLocateProtocol (&gEfiSmmSwDispatch2ProtocolGuid, NULL, (VOID**)&SwDispatch);
489   ASSERT_EFI_ERROR (Status);
490   SwContext.SwSmiInputValue = (UINTN) -1;
491   Status = SwDispatch->Register (SwDispatch, PhysicalPresenceCallback, &SwContext, &SwHandle);
492   ASSERT_EFI_ERROR (Status);
493   if (EFI_ERROR (Status)) {
494     return Status;
495   }
496   mTcgNvs->PhysicalPresence.SoftwareSmi = (UINT8) SwContext.SwSmiInputValue;
497 
498   SwContext.SwSmiInputValue = (UINTN) -1;
499   Status = SwDispatch->Register (SwDispatch, MemoryClearCallback, &SwContext, &SwHandle);
500   ASSERT_EFI_ERROR (Status);
501   if (EFI_ERROR (Status)) {
502     return Status;
503   }
504   mTcgNvs->MemoryClear.SoftwareSmi = (UINT8) SwContext.SwSmiInputValue;
505 
506   //
507   // Locate SmmVariableProtocol.
508   //
509   Status = gSmst->SmmLocateProtocol (&gEfiSmmVariableProtocolGuid, NULL, (VOID**)&mSmmVariable);
510   ASSERT_EFI_ERROR (Status);
511 
512   //
513   // Set TPM2 ACPI table
514   //
515   Status = PublishTpm2 ();
516   ASSERT_EFI_ERROR (Status);
517 
518 
519   return EFI_SUCCESS;
520 }
521 
522