SecurityPkg: Tcg2Smm: Fix type casting issue
[mirror_edk2.git] / SecurityPkg / Tcg / Tcg2Smm / Tcg2Smm.c
CommitLineData
1abfa4ce
JY
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
d967d6d9 12Copyright (c) 2015 - 2016, Intel Corporation. All rights reserved.<BR>\r
1abfa4ce
JY
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
d967d6d9
JY
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
3b5624b0
ZC
53 if (InterfaceId.Bits.InterfaceType == PTP_INTERFACE_IDENTIFIER_INTERFACE_TYPE_TIS) {\r
54 return PtpInterfaceTis;\r
55 }\r
56\r
d967d6d9
JY
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
3b5624b0 62\r
d967d6d9
JY
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
3b5624b0
ZC
69\r
70 //\r
71 // No Ptp interface available\r
72 //\r
73 return PtpInterfaceMax;\r
d967d6d9
JY
74}\r
75\r
1abfa4ce
JY
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\r
123 if (mTcgNvs->PhysicalPresence.Parameter == TCG_ACPI_FUNCTION_RETURN_REQUEST_RESPONSE_TO_OS) {\r
124 mTcgNvs->PhysicalPresence.ReturnCode = Tcg2PhysicalPresenceLibReturnOperationResponseToOsFunction (\r
125 &MostRecentRequest,\r
126 &Response\r
127 );\r
128 mTcgNvs->PhysicalPresence.LastRequest = MostRecentRequest;\r
129 mTcgNvs->PhysicalPresence.Response = Response;\r
130 return EFI_SUCCESS;\r
131 } else if ((mTcgNvs->PhysicalPresence.Parameter == TCG_ACPI_FUNCTION_SUBMIT_REQUEST_TO_BIOS) \r
132 || (mTcgNvs->PhysicalPresence.Parameter == TCG_ACPI_FUNCTION_SUBMIT_REQUEST_TO_BIOS_2)) {\r
133 mTcgNvs->PhysicalPresence.ReturnCode = Tcg2PhysicalPresenceLibSubmitRequestToPreOSFunction (\r
134 mTcgNvs->PhysicalPresence.Request,\r
135 mTcgNvs->PhysicalPresence.RequestParameter\r
136 );\r
137 } else if (mTcgNvs->PhysicalPresence.Parameter == TCG_ACPI_FUNCTION_GET_USER_CONFIRMATION_STATUS_FOR_REQUEST) {\r
138 mTcgNvs->PhysicalPresence.ReturnCode = Tcg2PhysicalPresenceLibGetUserConfirmationStatusFunction (mTcgNvs->PhysicalPresence.Request);\r
139 } \r
140\r
141 return EFI_SUCCESS;\r
142}\r
143\r
144\r
145/**\r
146 Software SMI callback for MemoryClear which is called from ACPI method.\r
147\r
148 Caution: This function may receive untrusted input.\r
149 Variable and ACPINvs are external input, so this function will validate\r
150 its data structure to be valid value.\r
151\r
152 @param[in] DispatchHandle The unique handle assigned to this handler by SmiHandlerRegister().\r
153 @param[in] Context Points to an optional handler context which was specified when the\r
154 handler was registered.\r
155 @param[in, out] CommBuffer A pointer to a collection of data in memory that will\r
156 be conveyed from a non-SMM environment into an SMM environment.\r
157 @param[in, out] CommBufferSize The size of the CommBuffer.\r
158\r
159 @retval EFI_SUCCESS The interrupt was handled successfully.\r
160\r
161**/\r
162EFI_STATUS\r
163EFIAPI\r
164MemoryClearCallback (\r
165 IN EFI_HANDLE DispatchHandle,\r
166 IN CONST VOID *Context,\r
167 IN OUT VOID *CommBuffer,\r
168 IN OUT UINTN *CommBufferSize\r
169 )\r
170{\r
171 EFI_STATUS Status;\r
172 UINTN DataSize;\r
173 UINT8 MorControl;\r
174\r
175 mTcgNvs->MemoryClear.ReturnCode = MOR_REQUEST_SUCCESS;\r
176 if (mTcgNvs->MemoryClear.Parameter == ACPI_FUNCTION_DSM_MEMORY_CLEAR_INTERFACE) {\r
177 MorControl = (UINT8) mTcgNvs->MemoryClear.Request;\r
178 } else if (mTcgNvs->MemoryClear.Parameter == ACPI_FUNCTION_PTS_CLEAR_MOR_BIT) {\r
179 DataSize = sizeof (UINT8);\r
180 Status = mSmmVariable->SmmGetVariable (\r
181 MEMORY_OVERWRITE_REQUEST_VARIABLE_NAME,\r
182 &gEfiMemoryOverwriteControlDataGuid,\r
183 NULL,\r
184 &DataSize,\r
185 &MorControl\r
186 );\r
187 if (EFI_ERROR (Status)) {\r
188 mTcgNvs->MemoryClear.ReturnCode = MOR_REQUEST_GENERAL_FAILURE;\r
189 DEBUG ((EFI_D_ERROR, "[TPM] Get MOR variable failure! Status = %r\n", Status));\r
190 return EFI_SUCCESS;\r
191 }\r
192\r
193 if (MOR_CLEAR_MEMORY_VALUE (MorControl) == 0x0) {\r
194 return EFI_SUCCESS;\r
195 }\r
196 MorControl &= ~MOR_CLEAR_MEMORY_BIT_MASK;\r
197 }\r
198\r
199 DataSize = sizeof (UINT8);\r
200 Status = mSmmVariable->SmmSetVariable (\r
201 MEMORY_OVERWRITE_REQUEST_VARIABLE_NAME,\r
202 &gEfiMemoryOverwriteControlDataGuid,\r
203 EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,\r
204 DataSize,\r
205 &MorControl\r
206 );\r
207 if (EFI_ERROR (Status)) { \r
208 mTcgNvs->MemoryClear.ReturnCode = MOR_REQUEST_GENERAL_FAILURE;\r
209 DEBUG ((EFI_D_ERROR, "[TPM] Set MOR variable failure! Status = %r\n", Status));\r
210 }\r
211\r
212 return EFI_SUCCESS;\r
213}\r
214\r
215/**\r
216 Find the operation region in TCG ACPI table by given Name and Size,\r
217 and initialize it if the region is found.\r
218\r
219 @param[in, out] Table The TPM item in ACPI table.\r
220 @param[in] Name The name string to find in TPM table.\r
221 @param[in] Size The size of the region to find.\r
222\r
223 @return The allocated address for the found region.\r
224\r
225**/\r
226VOID *\r
227AssignOpRegion (\r
228 EFI_ACPI_DESCRIPTION_HEADER *Table,\r
229 UINT32 Name,\r
230 UINT16 Size\r
231 )\r
232{\r
233 EFI_STATUS Status;\r
234 AML_OP_REGION_32_8 *OpRegion;\r
235 EFI_PHYSICAL_ADDRESS MemoryAddress;\r
236\r
237 MemoryAddress = SIZE_4GB - 1;\r
238\r
239 //\r
240 // Patch some pointers for the ASL code before loading the SSDT.\r
241 //\r
242 for (OpRegion = (AML_OP_REGION_32_8 *) (Table + 1);\r
243 OpRegion <= (AML_OP_REGION_32_8 *) ((UINT8 *) Table + Table->Length);\r
244 OpRegion = (AML_OP_REGION_32_8 *) ((UINT8 *) OpRegion + 1)) {\r
245 if ((OpRegion->OpRegionOp == AML_EXT_REGION_OP) && \r
246 (OpRegion->NameString == Name) &&\r
247 (OpRegion->DWordPrefix == AML_DWORD_PREFIX) &&\r
248 (OpRegion->BytePrefix == AML_BYTE_PREFIX)) {\r
249\r
250 Status = gBS->AllocatePages(AllocateMaxAddress, EfiACPIMemoryNVS, EFI_SIZE_TO_PAGES (Size), &MemoryAddress);\r
251 ASSERT_EFI_ERROR (Status);\r
252 ZeroMem ((VOID *)(UINTN)MemoryAddress, Size);\r
253 OpRegion->RegionOffset = (UINT32) (UINTN) MemoryAddress;\r
254 OpRegion->RegionLen = (UINT8) Size;\r
255 break;\r
256 }\r
257 }\r
258\r
259 return (VOID *) (UINTN) MemoryAddress;\r
260}\r
261\r
cd643013
ZC
262/**\r
263 Patch version string of Physical Presence interface supported by platform. The initial string tag in TPM \r
264ACPI table is "$PV".\r
265\r
266 @param[in, out] Table The TPM item in ACPI table.\r
267 @param[in] PPVer Version string of Physical Presence interface supported by platform.\r
268\r
269 @return The allocated address for the found region.\r
270\r
271**/\r
272EFI_STATUS\r
273UpdatePPVersion (\r
274 EFI_ACPI_DESCRIPTION_HEADER *Table,\r
275 CHAR8 *PPVer\r
276 )\r
277{\r
278 EFI_STATUS Status;\r
279 UINT8 *DataPtr;\r
280\r
281 //\r
282 // Patch some pointers for the ASL code before loading the SSDT.\r
283 //\r
284 for (DataPtr = (UINT8 *)(Table + 1);\r
285 DataPtr <= (UINT8 *) ((UINT8 *) Table + Table->Length - PHYSICAL_PRESENCE_VERSION_SIZE);\r
286 DataPtr += 1) {\r
0c687d02
ZC
287 if (AsciiStrCmp((CHAR8 *)DataPtr, PHYSICAL_PRESENCE_VERSION_TAG) == 0) {\r
288 Status = AsciiStrCpyS((CHAR8 *)DataPtr, PHYSICAL_PRESENCE_VERSION_SIZE, PPVer);\r
cd643013
ZC
289 DEBUG((EFI_D_INFO, "TPM2 Physical Presence Interface Version update status 0x%x\n", Status));\r
290 return Status;\r
291 }\r
292 }\r
293\r
294 return EFI_NOT_FOUND;\r
295}\r
296\r
1abfa4ce
JY
297/**\r
298 Initialize and publish TPM items in ACPI table.\r
299\r
300 @retval EFI_SUCCESS The TCG ACPI table is published successfully.\r
301 @retval Others The TCG ACPI table is not published.\r
302\r
303**/\r
304EFI_STATUS\r
305PublishAcpiTable (\r
306 VOID\r
307 )\r
308{\r
309 EFI_STATUS Status;\r
310 EFI_ACPI_TABLE_PROTOCOL *AcpiTable;\r
311 UINTN TableKey;\r
312 EFI_ACPI_DESCRIPTION_HEADER *Table;\r
313 UINTN TableSize;\r
314\r
315 Status = GetSectionFromFv (\r
316 &gEfiCallerIdGuid,\r
317 EFI_SECTION_RAW,\r
318 0,\r
319 (VOID **) &Table,\r
320 &TableSize\r
321 );\r
322 ASSERT_EFI_ERROR (Status);\r
323\r
cd643013
ZC
324 //\r
325 // Update Table version before measuring it to PCR\r
326 //\r
327 Status = UpdatePPVersion(Table, (CHAR8 *)PcdGetPtr(PcdTcgPhysicalPresenceInterfaceVer));\r
328 ASSERT_EFI_ERROR (Status);\r
1abfa4ce
JY
329\r
330 //\r
331 // Measure to PCR[0] with event EV_POST_CODE ACPI DATA\r
332 //\r
333 TpmMeasureAndLogData(\r
334 0,\r
335 EV_POST_CODE,\r
336 EV_POSTCODE_INFO_ACPI_DATA,\r
337 ACPI_DATA_LEN,\r
338 Table,\r
339 TableSize\r
340 );\r
341\r
342\r
343 ASSERT (Table->OemTableId == SIGNATURE_64 ('T', 'p', 'm', '2', 'T', 'a', 'b', 'l'));\r
344 CopyMem (Table->OemId, PcdGetPtr (PcdAcpiDefaultOemId), sizeof (Table->OemId) );\r
345 mTcgNvs = AssignOpRegion (Table, SIGNATURE_32 ('T', 'N', 'V', 'S'), (UINT16) sizeof (TCG_NVS));\r
346 ASSERT (mTcgNvs != NULL);\r
347\r
348 //\r
cd643013 349 // Publish the TPM ACPI table. Table is re-checksumed.\r
1abfa4ce
JY
350 //\r
351 Status = gBS->LocateProtocol (&gEfiAcpiTableProtocolGuid, NULL, (VOID **) &AcpiTable);\r
352 ASSERT_EFI_ERROR (Status);\r
353\r
354 TableKey = 0;\r
355 Status = AcpiTable->InstallAcpiTable (\r
356 AcpiTable,\r
357 Table,\r
358 TableSize,\r
359 &TableKey\r
360 );\r
361 ASSERT_EFI_ERROR (Status);\r
362\r
363 return Status;\r
364}\r
365\r
366/**\r
367 Publish TPM2 ACPI table\r
368\r
369 @retval EFI_SUCCESS The TPM2 ACPI table is published successfully.\r
370 @retval Others The TPM2 ACPI table is not published.\r
371\r
372**/\r
373EFI_STATUS\r
374PublishTpm2 (\r
375 VOID\r
376 )\r
377{\r
378 EFI_STATUS Status;\r
379 EFI_ACPI_TABLE_PROTOCOL *AcpiTable;\r
380 UINTN TableKey;\r
381 UINT64 OemTableId;\r
d967d6d9
JY
382 EFI_TPM2_ACPI_CONTROL_AREA *ControlArea;\r
383 PTP_INTERFACE_TYPE InterfaceType;\r
1abfa4ce
JY
384\r
385 //\r
386 // Measure to PCR[0] with event EV_POST_CODE ACPI DATA\r
387 //\r
388 TpmMeasureAndLogData(\r
389 0,\r
390 EV_POST_CODE,\r
391 EV_POSTCODE_INFO_ACPI_DATA,\r
392 ACPI_DATA_LEN,\r
393 &mTpm2AcpiTemplate,\r
394 sizeof(mTpm2AcpiTemplate)\r
395 );\r
396\r
d967d6d9
JY
397 InterfaceType = GetPtpInterface ((VOID *) (UINTN) PcdGet64 (PcdTpmBaseAddress));\r
398 switch (InterfaceType) {\r
399 case PtpInterfaceCrb:\r
400 mTpm2AcpiTemplate.StartMethod = EFI_TPM2_ACPI_TABLE_START_METHOD_COMMAND_RESPONSE_BUFFER_INTERFACE;\r
401 mTpm2AcpiTemplate.AddressOfControlArea = PcdGet64 (PcdTpmBaseAddress) + 0x40;\r
402 ControlArea = (EFI_TPM2_ACPI_CONTROL_AREA *)(UINTN)mTpm2AcpiTemplate.AddressOfControlArea;\r
403 ControlArea->CommandSize = 0xF80;\r
404 ControlArea->ResponseSize = 0xF80;\r
405 ControlArea->Command = PcdGet64 (PcdTpmBaseAddress) + 0x80;\r
406 ControlArea->Response = PcdGet64 (PcdTpmBaseAddress) + 0x80;\r
407 break;\r
408 case PtpInterfaceFifo:\r
409 case PtpInterfaceTis:\r
410 break;\r
411 default:\r
3b5624b0 412 DEBUG((EFI_D_ERROR, "TPM2 InterfaceType get error! %d\n", InterfaceType));\r
d967d6d9
JY
413 break;\r
414 }\r
415\r
1abfa4ce
JY
416 CopyMem (mTpm2AcpiTemplate.Header.OemId, PcdGetPtr (PcdAcpiDefaultOemId), sizeof (mTpm2AcpiTemplate.Header.OemId));\r
417 OemTableId = PcdGet64 (PcdAcpiDefaultOemTableId);\r
418 CopyMem (&mTpm2AcpiTemplate.Header.OemTableId, &OemTableId, sizeof (UINT64));\r
419 mTpm2AcpiTemplate.Header.OemRevision = PcdGet32 (PcdAcpiDefaultOemRevision);\r
420 mTpm2AcpiTemplate.Header.CreatorId = PcdGet32 (PcdAcpiDefaultCreatorId);\r
421 mTpm2AcpiTemplate.Header.CreatorRevision = PcdGet32 (PcdAcpiDefaultCreatorRevision);\r
422\r
423 //\r
424 // Construct ACPI table\r
425 //\r
426 Status = gBS->LocateProtocol (&gEfiAcpiTableProtocolGuid, NULL, (VOID **) &AcpiTable);\r
427 ASSERT_EFI_ERROR (Status);\r
428\r
429 Status = AcpiTable->InstallAcpiTable (\r
430 AcpiTable,\r
431 &mTpm2AcpiTemplate,\r
432 sizeof(mTpm2AcpiTemplate),\r
433 &TableKey\r
434 );\r
435 ASSERT_EFI_ERROR (Status);\r
436\r
437 return Status;\r
438}\r
439\r
440/**\r
441 The driver's entry point.\r
442\r
443 It install callbacks for TPM physical presence and MemoryClear, and locate \r
444 SMM variable to be used in the callback function.\r
445\r
446 @param[in] ImageHandle The firmware allocated handle for the EFI image. \r
447 @param[in] SystemTable A pointer to the EFI System Table.\r
448 \r
449 @retval EFI_SUCCESS The entry point is executed successfully.\r
450 @retval Others Some error occurs when executing this entry point.\r
451\r
452**/\r
453EFI_STATUS\r
454EFIAPI\r
455InitializeTcgSmm (\r
456 IN EFI_HANDLE ImageHandle,\r
457 IN EFI_SYSTEM_TABLE *SystemTable\r
458 )\r
459{\r
460 EFI_STATUS Status;\r
461 EFI_SMM_SW_DISPATCH2_PROTOCOL *SwDispatch;\r
462 EFI_SMM_SW_REGISTER_CONTEXT SwContext;\r
463 EFI_HANDLE SwHandle;\r
464\r
465 if (!CompareGuid (PcdGetPtr(PcdTpmInstanceGuid), &gEfiTpmDeviceInstanceTpm20DtpmGuid)){\r
466 DEBUG ((EFI_D_ERROR, "No TPM2 DTPM instance required!\n"));\r
467 return EFI_UNSUPPORTED;\r
468 }\r
469\r
470 Status = PublishAcpiTable ();\r
471 ASSERT_EFI_ERROR (Status);\r
472\r
473 //\r
474 // Get the Sw dispatch protocol and register SMI callback functions.\r
475 //\r
476 Status = gSmst->SmmLocateProtocol (&gEfiSmmSwDispatch2ProtocolGuid, NULL, (VOID**)&SwDispatch);\r
477 ASSERT_EFI_ERROR (Status);\r
478 SwContext.SwSmiInputValue = (UINTN) -1;\r
479 Status = SwDispatch->Register (SwDispatch, PhysicalPresenceCallback, &SwContext, &SwHandle);\r
480 ASSERT_EFI_ERROR (Status);\r
481 if (EFI_ERROR (Status)) {\r
482 return Status;\r
483 }\r
484 mTcgNvs->PhysicalPresence.SoftwareSmi = (UINT8) SwContext.SwSmiInputValue;\r
485\r
486 SwContext.SwSmiInputValue = (UINTN) -1;\r
487 Status = SwDispatch->Register (SwDispatch, MemoryClearCallback, &SwContext, &SwHandle);\r
488 ASSERT_EFI_ERROR (Status);\r
489 if (EFI_ERROR (Status)) {\r
490 return Status;\r
491 }\r
492 mTcgNvs->MemoryClear.SoftwareSmi = (UINT8) SwContext.SwSmiInputValue;\r
493 \r
494 //\r
495 // Locate SmmVariableProtocol.\r
496 //\r
497 Status = gSmst->SmmLocateProtocol (&gEfiSmmVariableProtocolGuid, NULL, (VOID**)&mSmmVariable);\r
498 ASSERT_EFI_ERROR (Status);\r
499\r
500 //\r
501 // Set TPM2 ACPI table\r
502 //\r
503 Status = PublishTpm2 ();\r
504 ASSERT_EFI_ERROR (Status);\r
505\r
506\r
507 return EFI_SUCCESS;\r
508}\r
509\r