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 12Copyright (c) 2015 - 2017, Intel Corporation. All rights reserved.<BR> 13This program and the accompanying materials 14are licensed and made available under the terms and conditions of the BSD License 15which accompanies this distribution. The full text of the license may be found at 16http://opensource.org/licenses/bsd-license.php 17 18THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, 19WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. 20 21**/ 22 23#include "Tcg2Smm.h" 24 25typedef 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**/ 39PTP_INTERFACE_TYPE 40GetPtpInterface ( 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 76EFI_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 91EFI_SMM_VARIABLE_PROTOCOL *mSmmVariable; 92TCG_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**/ 111EFI_STATUS 112EFIAPI 113PhysicalPresenceCallback ( 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**/ 170EFI_STATUS 171EFIAPI 172MemoryClearCallback ( 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**/ 234VOID * 235AssignOpRegion ( 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 272ACPI 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**/ 280EFI_STATUS 281UpdatePPVersion ( 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**/ 313EFI_STATUS 314UpdateHID ( 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 // ManufacturerID 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((DEBUG_INFO, "TPM2 ACPI _HID is patched to %a\n", DataPtr)); 400 401 return Status; 402 } 403 } 404 405 DEBUG((EFI_D_ERROR, "TPM2 ACPI HID TAG for patch not found!\n")); 406 return EFI_NOT_FOUND; 407} 408 409/** 410 Initialize and publish TPM items in ACPI table. 411 412 @retval EFI_SUCCESS The TCG ACPI table is published successfully. 413 @retval Others The TCG ACPI table is not published. 414 415**/ 416EFI_STATUS 417PublishAcpiTable ( 418 VOID 419 ) 420{ 421 EFI_STATUS Status; 422 EFI_ACPI_TABLE_PROTOCOL *AcpiTable; 423 UINTN TableKey; 424 EFI_ACPI_DESCRIPTION_HEADER *Table; 425 UINTN TableSize; 426 427 Status = GetSectionFromFv ( 428 &gEfiCallerIdGuid, 429 EFI_SECTION_RAW, 430 0, 431 (VOID **) &Table, 432 &TableSize 433 ); 434 ASSERT_EFI_ERROR (Status); 435 436 // 437 // Update Table version before measuring it to PCR 438 // 439 Status = UpdatePPVersion(Table, (CHAR8 *)PcdGetPtr(PcdTcgPhysicalPresenceInterfaceVer)); 440 ASSERT_EFI_ERROR (Status); 441 442 // 443 // Update TPM2 HID before measuring it to PCR 444 // 445 Status = UpdateHID(Table); 446 if (EFI_ERROR(Status)) { 447 return Status; 448 } 449 450 // 451 // Measure to PCR[0] with event EV_POST_CODE ACPI DATA 452 // 453 TpmMeasureAndLogData( 454 0, 455 EV_POST_CODE, 456 EV_POSTCODE_INFO_ACPI_DATA, 457 ACPI_DATA_LEN, 458 Table, 459 TableSize 460 ); 461 462 463 ASSERT (Table->OemTableId == SIGNATURE_64 ('T', 'p', 'm', '2', 'T', 'a', 'b', 'l')); 464 CopyMem (Table->OemId, PcdGetPtr (PcdAcpiDefaultOemId), sizeof (Table->OemId) ); 465 mTcgNvs = AssignOpRegion (Table, SIGNATURE_32 ('T', 'N', 'V', 'S'), (UINT16) sizeof (TCG_NVS)); 466 ASSERT (mTcgNvs != NULL); 467 468 // 469 // Publish the TPM ACPI table. Table is re-checksumed. 470 // 471 Status = gBS->LocateProtocol (&gEfiAcpiTableProtocolGuid, NULL, (VOID **) &AcpiTable); 472 ASSERT_EFI_ERROR (Status); 473 474 TableKey = 0; 475 Status = AcpiTable->InstallAcpiTable ( 476 AcpiTable, 477 Table, 478 TableSize, 479 &TableKey 480 ); 481 ASSERT_EFI_ERROR (Status); 482 483 return Status; 484} 485 486/** 487 Publish TPM2 ACPI table 488 489 @retval EFI_SUCCESS The TPM2 ACPI table is published successfully. 490 @retval Others The TPM2 ACPI table is not published. 491 492**/ 493EFI_STATUS 494PublishTpm2 ( 495 VOID 496 ) 497{ 498 EFI_STATUS Status; 499 EFI_ACPI_TABLE_PROTOCOL *AcpiTable; 500 UINTN TableKey; 501 UINT64 OemTableId; 502 EFI_TPM2_ACPI_CONTROL_AREA *ControlArea; 503 PTP_INTERFACE_TYPE InterfaceType; 504 505 // 506 // Measure to PCR[0] with event EV_POST_CODE ACPI DATA 507 // 508 TpmMeasureAndLogData( 509 0, 510 EV_POST_CODE, 511 EV_POSTCODE_INFO_ACPI_DATA, 512 ACPI_DATA_LEN, 513 &mTpm2AcpiTemplate, 514 sizeof(mTpm2AcpiTemplate) 515 ); 516 517 InterfaceType = GetPtpInterface ((VOID *) (UINTN) PcdGet64 (PcdTpmBaseAddress)); 518 switch (InterfaceType) { 519 case PtpInterfaceCrb: 520 mTpm2AcpiTemplate.StartMethod = EFI_TPM2_ACPI_TABLE_START_METHOD_COMMAND_RESPONSE_BUFFER_INTERFACE; 521 mTpm2AcpiTemplate.AddressOfControlArea = PcdGet64 (PcdTpmBaseAddress) + 0x40; 522 ControlArea = (EFI_TPM2_ACPI_CONTROL_AREA *)(UINTN)mTpm2AcpiTemplate.AddressOfControlArea; 523 ControlArea->CommandSize = 0xF80; 524 ControlArea->ResponseSize = 0xF80; 525 ControlArea->Command = PcdGet64 (PcdTpmBaseAddress) + 0x80; 526 ControlArea->Response = PcdGet64 (PcdTpmBaseAddress) + 0x80; 527 break; 528 case PtpInterfaceFifo: 529 case PtpInterfaceTis: 530 break; 531 default: 532 DEBUG((EFI_D_ERROR, "TPM2 InterfaceType get error! %d\n", InterfaceType)); 533 break; 534 } 535 536 CopyMem (mTpm2AcpiTemplate.Header.OemId, PcdGetPtr (PcdAcpiDefaultOemId), sizeof (mTpm2AcpiTemplate.Header.OemId)); 537 OemTableId = PcdGet64 (PcdAcpiDefaultOemTableId); 538 CopyMem (&mTpm2AcpiTemplate.Header.OemTableId, &OemTableId, sizeof (UINT64)); 539 mTpm2AcpiTemplate.Header.OemRevision = PcdGet32 (PcdAcpiDefaultOemRevision); 540 mTpm2AcpiTemplate.Header.CreatorId = PcdGet32 (PcdAcpiDefaultCreatorId); 541 mTpm2AcpiTemplate.Header.CreatorRevision = PcdGet32 (PcdAcpiDefaultCreatorRevision); 542 543 // 544 // Construct ACPI table 545 // 546 Status = gBS->LocateProtocol (&gEfiAcpiTableProtocolGuid, NULL, (VOID **) &AcpiTable); 547 ASSERT_EFI_ERROR (Status); 548 549 Status = AcpiTable->InstallAcpiTable ( 550 AcpiTable, 551 &mTpm2AcpiTemplate, 552 sizeof(mTpm2AcpiTemplate), 553 &TableKey 554 ); 555 ASSERT_EFI_ERROR (Status); 556 557 return Status; 558} 559 560/** 561 The driver's entry point. 562 563 It install callbacks for TPM physical presence and MemoryClear, and locate 564 SMM variable to be used in the callback function. 565 566 @param[in] ImageHandle The firmware allocated handle for the EFI image. 567 @param[in] SystemTable A pointer to the EFI System Table. 568 569 @retval EFI_SUCCESS The entry point is executed successfully. 570 @retval Others Some error occurs when executing this entry point. 571 572**/ 573EFI_STATUS 574EFIAPI 575InitializeTcgSmm ( 576 IN EFI_HANDLE ImageHandle, 577 IN EFI_SYSTEM_TABLE *SystemTable 578 ) 579{ 580 EFI_STATUS Status; 581 EFI_SMM_SW_DISPATCH2_PROTOCOL *SwDispatch; 582 EFI_SMM_SW_REGISTER_CONTEXT SwContext; 583 EFI_HANDLE SwHandle; 584 585 if (!CompareGuid (PcdGetPtr(PcdTpmInstanceGuid), &gEfiTpmDeviceInstanceTpm20DtpmGuid)){ 586 DEBUG ((EFI_D_ERROR, "No TPM2 DTPM instance required!\n")); 587 return EFI_UNSUPPORTED; 588 } 589 590 Status = PublishAcpiTable (); 591 ASSERT_EFI_ERROR (Status); 592 593 // 594 // Get the Sw dispatch protocol and register SMI callback functions. 595 // 596 Status = gSmst->SmmLocateProtocol (&gEfiSmmSwDispatch2ProtocolGuid, NULL, (VOID**)&SwDispatch); 597 ASSERT_EFI_ERROR (Status); 598 SwContext.SwSmiInputValue = (UINTN) -1; 599 Status = SwDispatch->Register (SwDispatch, PhysicalPresenceCallback, &SwContext, &SwHandle); 600 ASSERT_EFI_ERROR (Status); 601 if (EFI_ERROR (Status)) { 602 return Status; 603 } 604 mTcgNvs->PhysicalPresence.SoftwareSmi = (UINT8) SwContext.SwSmiInputValue; 605 606 SwContext.SwSmiInputValue = (UINTN) -1; 607 Status = SwDispatch->Register (SwDispatch, MemoryClearCallback, &SwContext, &SwHandle); 608 ASSERT_EFI_ERROR (Status); 609 if (EFI_ERROR (Status)) { 610 return Status; 611 } 612 mTcgNvs->MemoryClear.SoftwareSmi = (UINT8) SwContext.SwSmiInputValue; 613 614 // 615 // Locate SmmVariableProtocol. 616 // 617 Status = gSmst->SmmLocateProtocol (&gEfiSmmVariableProtocolGuid, NULL, (VOID**)&mSmmVariable); 618 ASSERT_EFI_ERROR (Status); 619 620 // 621 // Set TPM2 ACPI table 622 // 623 Status = PublishTpm2 (); 624 ASSERT_EFI_ERROR (Status); 625 626 627 return EFI_SUCCESS; 628} 629 630