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