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