]> git.proxmox.com Git - mirror_edk2.git/blame - SecurityPkg/Tcg/Tcg2Smm/Tcg2Smm.c
SecurityPkg Tcg2ConfigDxe: Add setup option to configure PPI version
[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
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
edb0fda2
ZC
122 UINT32 OperationRequest;\r
123 UINT32 RequestParameter;\r
124\r
1abfa4ce
JY
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
edb0fda2
ZC
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
1abfa4ce 142 );\r
edb0fda2
ZC
143 mTcgNvs->PhysicalPresence.Request = OperationRequest;\r
144 mTcgNvs->PhysicalPresence.RequestParameter = RequestParameter;\r
1abfa4ce 145 } else if (mTcgNvs->PhysicalPresence.Parameter == TCG_ACPI_FUNCTION_GET_USER_CONFIRMATION_STATUS_FOR_REQUEST) {\r
053f31e3
ZC
146 mTcgNvs->PhysicalPresence.ReturnCode = Tcg2PhysicalPresenceLibGetUserConfirmationStatusFunction (mTcgNvs->PPRequestUserConfirm);\r
147 }\r
1abfa4ce
JY
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
cd643013
ZC
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
0c687d02
ZC
295 if (AsciiStrCmp((CHAR8 *)DataPtr, PHYSICAL_PRESENCE_VERSION_TAG) == 0) {\r
296 Status = AsciiStrCpyS((CHAR8 *)DataPtr, PHYSICAL_PRESENCE_VERSION_SIZE, PPVer);\r
cd643013
ZC
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
73126ac2
ZC
305/**\r
306 Patch TPM2 device HID string. The initial string tag in TPM2 ACPI table is "NNN0000".\r
307\r
308 @param[in, out] Table The TPM2 SSDT ACPI table.\r
309\r
310 @return HID Update status.\r
311\r
312**/\r
313EFI_STATUS\r
314UpdateHID (\r
315 EFI_ACPI_DESCRIPTION_HEADER *Table\r
316 )\r
317{\r
318 EFI_STATUS Status;\r
319 UINT8 *DataPtr;\r
3304abc1 320 CHAR8 Hid[TPM_HID_ACPI_SIZE];\r
73126ac2
ZC
321 UINT32 ManufacturerID;\r
322 UINT32 FirmwareVersion1;\r
323 UINT32 FirmwareVersion2;\r
324 BOOLEAN PnpHID;\r
325\r
326 PnpHID = TRUE;\r
327\r
328 //\r
329 // Initialize HID with Default PNP string\r
330 //\r
3304abc1 331 ZeroMem(Hid, TPM_HID_ACPI_SIZE);\r
73126ac2
ZC
332\r
333 //\r
334 // Get Manufacturer ID\r
335 //\r
336 Status = Tpm2GetCapabilityManufactureID(&ManufacturerID);\r
337 if (!EFI_ERROR(Status)) {\r
338 DEBUG((EFI_D_INFO, "TPM_PT_MANUFACTURER 0x%08x\n", ManufacturerID));\r
339 //\r
a6e0e994 340 // ManufacturerID defined in TCG Vendor ID Registry \r
73126ac2
ZC
341 // may tailed with 0x00 or 0x20\r
342 //\r
343 if ((ManufacturerID >> 24) == 0x00 || ((ManufacturerID >> 24) == 0x20)) {\r
344 //\r
345 // HID containing PNP ID "NNN####"\r
346 // NNN is uppercase letter for Vendor ID specified by manufacturer\r
347 //\r
3304abc1 348 CopyMem(Hid, &ManufacturerID, 3);\r
73126ac2
ZC
349 } else {\r
350 //\r
351 // HID containing ACP ID "NNNN####"\r
352 // NNNN is uppercase letter for Vendor ID specified by manufacturer\r
353 //\r
3304abc1 354 CopyMem(Hid, &ManufacturerID, 4);\r
73126ac2
ZC
355 PnpHID = FALSE;\r
356 }\r
357 } else {\r
358 DEBUG ((EFI_D_ERROR, "Get TPM_PT_MANUFACTURER failed %x!\n", Status));\r
359 ASSERT(FALSE);\r
360 return Status;\r
361 }\r
362\r
363 Status = Tpm2GetCapabilityFirmwareVersion(&FirmwareVersion1, &FirmwareVersion2);\r
364 if (!EFI_ERROR(Status)) {\r
365 DEBUG((EFI_D_INFO, "TPM_PT_FIRMWARE_VERSION_1 0x%x\n", FirmwareVersion1));\r
366 DEBUG((EFI_D_INFO, "TPM_PT_FIRMWARE_VERSION_2 0x%x\n", FirmwareVersion2));\r
367 //\r
368 // #### is Firmware Version 1\r
369 //\r
370 if (PnpHID) {\r
3304abc1 371 AsciiSPrint(Hid + 3, TPM_HID_PNP_SIZE - 3, "%02d%02d", ((FirmwareVersion1 & 0xFFFF0000) >> 16), (FirmwareVersion1 && 0x0000FFFF));\r
73126ac2 372 } else {\r
3304abc1 373 AsciiSPrint(Hid + 4, TPM_HID_ACPI_SIZE - 4, "%02d%02d", ((FirmwareVersion1 & 0xFFFF0000) >> 16), (FirmwareVersion1 && 0x0000FFFF));\r
73126ac2
ZC
374 }\r
375 \r
376 } else {\r
377 DEBUG ((EFI_D_ERROR, "Get TPM_PT_FIRMWARE_VERSION_X failed %x!\n", Status));\r
378 ASSERT(FALSE);\r
379 return Status;\r
380 }\r
381\r
382 //\r
383 // Patch HID in ASL code before loading the SSDT.\r
384 //\r
385 for (DataPtr = (UINT8 *)(Table + 1);\r
386 DataPtr <= (UINT8 *) ((UINT8 *) Table + Table->Length - TPM_HID_PNP_SIZE);\r
387 DataPtr += 1) {\r
388 if (AsciiStrCmp((CHAR8 *)DataPtr, TPM_HID_TAG) == 0) {\r
389 if (PnpHID) {\r
3304abc1 390 CopyMem(DataPtr, Hid, TPM_HID_PNP_SIZE);\r
73126ac2 391 //\r
9a9fa14e 392 // if HID is PNP ID, patch the last byte in HID TAG to Noop\r
73126ac2 393 //\r
9a9fa14e
ZC
394 *(DataPtr + TPM_HID_PNP_SIZE) = AML_NOOP_OP;\r
395 } else {\r
396\r
3304abc1 397 CopyMem(DataPtr, Hid, TPM_HID_ACPI_SIZE);\r
73126ac2 398 }\r
a6e0e994
ZC
399 DEBUG((DEBUG_INFO, "TPM2 ACPI _HID is patched to %a\n", DataPtr));\r
400\r
73126ac2
ZC
401 return Status;\r
402 }\r
403 }\r
404\r
405 DEBUG((EFI_D_ERROR, "TPM2 ACPI HID TAG for patch not found!\n"));\r
406 return EFI_NOT_FOUND;\r
407}\r
408\r
1abfa4ce
JY
409/**\r
410 Initialize and publish TPM items in ACPI table.\r
411\r
412 @retval EFI_SUCCESS The TCG ACPI table is published successfully.\r
413 @retval Others The TCG ACPI table is not published.\r
414\r
415**/\r
416EFI_STATUS\r
417PublishAcpiTable (\r
418 VOID\r
419 )\r
420{\r
421 EFI_STATUS Status;\r
422 EFI_ACPI_TABLE_PROTOCOL *AcpiTable;\r
423 UINTN TableKey;\r
424 EFI_ACPI_DESCRIPTION_HEADER *Table;\r
425 UINTN TableSize;\r
426\r
427 Status = GetSectionFromFv (\r
428 &gEfiCallerIdGuid,\r
429 EFI_SECTION_RAW,\r
430 0,\r
431 (VOID **) &Table,\r
432 &TableSize\r
433 );\r
434 ASSERT_EFI_ERROR (Status);\r
435\r
cd643013
ZC
436 //\r
437 // Update Table version before measuring it to PCR\r
438 //\r
439 Status = UpdatePPVersion(Table, (CHAR8 *)PcdGetPtr(PcdTcgPhysicalPresenceInterfaceVer));\r
440 ASSERT_EFI_ERROR (Status);\r
1abfa4ce 441\r
dd6d0a52
SZ
442 DEBUG ((\r
443 DEBUG_INFO,\r
444 "Current physical presence interface version - %a\n",\r
445 (CHAR8 *) PcdGetPtr(PcdTcgPhysicalPresenceInterfaceVer)\r
446 ));\r
447\r
73126ac2
ZC
448 //\r
449 // Update TPM2 HID before measuring it to PCR\r
450 //\r
451 Status = UpdateHID(Table);\r
452 if (EFI_ERROR(Status)) {\r
453 return Status;\r
454 }\r
455\r
1abfa4ce
JY
456 //\r
457 // Measure to PCR[0] with event EV_POST_CODE ACPI DATA\r
458 //\r
459 TpmMeasureAndLogData(\r
460 0,\r
461 EV_POST_CODE,\r
462 EV_POSTCODE_INFO_ACPI_DATA,\r
463 ACPI_DATA_LEN,\r
464 Table,\r
465 TableSize\r
466 );\r
467\r
468\r
469 ASSERT (Table->OemTableId == SIGNATURE_64 ('T', 'p', 'm', '2', 'T', 'a', 'b', 'l'));\r
470 CopyMem (Table->OemId, PcdGetPtr (PcdAcpiDefaultOemId), sizeof (Table->OemId) );\r
471 mTcgNvs = AssignOpRegion (Table, SIGNATURE_32 ('T', 'N', 'V', 'S'), (UINT16) sizeof (TCG_NVS));\r
472 ASSERT (mTcgNvs != NULL);\r
473\r
474 //\r
cd643013 475 // Publish the TPM ACPI table. Table is re-checksumed.\r
1abfa4ce
JY
476 //\r
477 Status = gBS->LocateProtocol (&gEfiAcpiTableProtocolGuid, NULL, (VOID **) &AcpiTable);\r
478 ASSERT_EFI_ERROR (Status);\r
479\r
480 TableKey = 0;\r
481 Status = AcpiTable->InstallAcpiTable (\r
482 AcpiTable,\r
483 Table,\r
484 TableSize,\r
485 &TableKey\r
486 );\r
487 ASSERT_EFI_ERROR (Status);\r
488\r
489 return Status;\r
490}\r
491\r
492/**\r
493 Publish TPM2 ACPI table\r
494\r
495 @retval EFI_SUCCESS The TPM2 ACPI table is published successfully.\r
496 @retval Others The TPM2 ACPI table is not published.\r
497\r
498**/\r
499EFI_STATUS\r
500PublishTpm2 (\r
501 VOID\r
502 )\r
503{\r
504 EFI_STATUS Status;\r
505 EFI_ACPI_TABLE_PROTOCOL *AcpiTable;\r
506 UINTN TableKey;\r
507 UINT64 OemTableId;\r
d967d6d9
JY
508 EFI_TPM2_ACPI_CONTROL_AREA *ControlArea;\r
509 PTP_INTERFACE_TYPE InterfaceType;\r
1abfa4ce
JY
510\r
511 //\r
512 // Measure to PCR[0] with event EV_POST_CODE ACPI DATA\r
513 //\r
514 TpmMeasureAndLogData(\r
515 0,\r
516 EV_POST_CODE,\r
517 EV_POSTCODE_INFO_ACPI_DATA,\r
518 ACPI_DATA_LEN,\r
519 &mTpm2AcpiTemplate,\r
520 sizeof(mTpm2AcpiTemplate)\r
521 );\r
522\r
d967d6d9
JY
523 InterfaceType = GetPtpInterface ((VOID *) (UINTN) PcdGet64 (PcdTpmBaseAddress));\r
524 switch (InterfaceType) {\r
525 case PtpInterfaceCrb:\r
526 mTpm2AcpiTemplate.StartMethod = EFI_TPM2_ACPI_TABLE_START_METHOD_COMMAND_RESPONSE_BUFFER_INTERFACE;\r
527 mTpm2AcpiTemplate.AddressOfControlArea = PcdGet64 (PcdTpmBaseAddress) + 0x40;\r
528 ControlArea = (EFI_TPM2_ACPI_CONTROL_AREA *)(UINTN)mTpm2AcpiTemplate.AddressOfControlArea;\r
529 ControlArea->CommandSize = 0xF80;\r
530 ControlArea->ResponseSize = 0xF80;\r
531 ControlArea->Command = PcdGet64 (PcdTpmBaseAddress) + 0x80;\r
532 ControlArea->Response = PcdGet64 (PcdTpmBaseAddress) + 0x80;\r
533 break;\r
534 case PtpInterfaceFifo:\r
535 case PtpInterfaceTis:\r
536 break;\r
537 default:\r
3b5624b0 538 DEBUG((EFI_D_ERROR, "TPM2 InterfaceType get error! %d\n", InterfaceType));\r
d967d6d9
JY
539 break;\r
540 }\r
541\r
1abfa4ce
JY
542 CopyMem (mTpm2AcpiTemplate.Header.OemId, PcdGetPtr (PcdAcpiDefaultOemId), sizeof (mTpm2AcpiTemplate.Header.OemId));\r
543 OemTableId = PcdGet64 (PcdAcpiDefaultOemTableId);\r
544 CopyMem (&mTpm2AcpiTemplate.Header.OemTableId, &OemTableId, sizeof (UINT64));\r
545 mTpm2AcpiTemplate.Header.OemRevision = PcdGet32 (PcdAcpiDefaultOemRevision);\r
546 mTpm2AcpiTemplate.Header.CreatorId = PcdGet32 (PcdAcpiDefaultCreatorId);\r
547 mTpm2AcpiTemplate.Header.CreatorRevision = PcdGet32 (PcdAcpiDefaultCreatorRevision);\r
548\r
549 //\r
550 // Construct ACPI table\r
551 //\r
552 Status = gBS->LocateProtocol (&gEfiAcpiTableProtocolGuid, NULL, (VOID **) &AcpiTable);\r
553 ASSERT_EFI_ERROR (Status);\r
554\r
555 Status = AcpiTable->InstallAcpiTable (\r
556 AcpiTable,\r
557 &mTpm2AcpiTemplate,\r
558 sizeof(mTpm2AcpiTemplate),\r
559 &TableKey\r
560 );\r
561 ASSERT_EFI_ERROR (Status);\r
562\r
563 return Status;\r
564}\r
565\r
566/**\r
567 The driver's entry point.\r
568\r
569 It install callbacks for TPM physical presence and MemoryClear, and locate \r
570 SMM variable to be used in the callback function.\r
571\r
572 @param[in] ImageHandle The firmware allocated handle for the EFI image. \r
573 @param[in] SystemTable A pointer to the EFI System Table.\r
574 \r
575 @retval EFI_SUCCESS The entry point is executed successfully.\r
576 @retval Others Some error occurs when executing this entry point.\r
577\r
578**/\r
579EFI_STATUS\r
580EFIAPI\r
581InitializeTcgSmm (\r
582 IN EFI_HANDLE ImageHandle,\r
583 IN EFI_SYSTEM_TABLE *SystemTable\r
584 )\r
585{\r
586 EFI_STATUS Status;\r
587 EFI_SMM_SW_DISPATCH2_PROTOCOL *SwDispatch;\r
588 EFI_SMM_SW_REGISTER_CONTEXT SwContext;\r
589 EFI_HANDLE SwHandle;\r
590\r
591 if (!CompareGuid (PcdGetPtr(PcdTpmInstanceGuid), &gEfiTpmDeviceInstanceTpm20DtpmGuid)){\r
592 DEBUG ((EFI_D_ERROR, "No TPM2 DTPM instance required!\n"));\r
593 return EFI_UNSUPPORTED;\r
594 }\r
595\r
596 Status = PublishAcpiTable ();\r
597 ASSERT_EFI_ERROR (Status);\r
598\r
599 //\r
600 // Get the Sw dispatch protocol and register SMI callback functions.\r
601 //\r
602 Status = gSmst->SmmLocateProtocol (&gEfiSmmSwDispatch2ProtocolGuid, NULL, (VOID**)&SwDispatch);\r
603 ASSERT_EFI_ERROR (Status);\r
604 SwContext.SwSmiInputValue = (UINTN) -1;\r
605 Status = SwDispatch->Register (SwDispatch, PhysicalPresenceCallback, &SwContext, &SwHandle);\r
606 ASSERT_EFI_ERROR (Status);\r
607 if (EFI_ERROR (Status)) {\r
608 return Status;\r
609 }\r
610 mTcgNvs->PhysicalPresence.SoftwareSmi = (UINT8) SwContext.SwSmiInputValue;\r
611\r
612 SwContext.SwSmiInputValue = (UINTN) -1;\r
613 Status = SwDispatch->Register (SwDispatch, MemoryClearCallback, &SwContext, &SwHandle);\r
614 ASSERT_EFI_ERROR (Status);\r
615 if (EFI_ERROR (Status)) {\r
616 return Status;\r
617 }\r
618 mTcgNvs->MemoryClear.SoftwareSmi = (UINT8) SwContext.SwSmiInputValue;\r
619 \r
620 //\r
621 // Locate SmmVariableProtocol.\r
622 //\r
623 Status = gSmst->SmmLocateProtocol (&gEfiSmmVariableProtocolGuid, NULL, (VOID**)&mSmmVariable);\r
624 ASSERT_EFI_ERROR (Status);\r
625\r
626 //\r
627 // Set TPM2 ACPI table\r
628 //\r
629 Status = PublishTpm2 ();\r
630 ASSERT_EFI_ERROR (Status);\r
631\r
632\r
633 return EFI_SUCCESS;\r
634}\r
635\r