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