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