\r
PhysicalPresenceCallback() and MemoryClearCallback() will receive untrusted input and do some check.\r
\r
-Copyright (c) 2015 - 2017, Intel Corporation. All rights reserved.<BR>\r
-This program and the accompanying materials \r
-are licensed and made available under the terms and conditions of the BSD License \r
-which accompanies this distribution. The full text of the license may be found at \r
-http://opensource.org/licenses/bsd-license.php\r
-\r
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+Copyright (c) 2015 - 2018, Intel Corporation. All rights reserved.<BR>\r
+Copyright (c) Microsoft Corporation.\r
+SPDX-License-Identifier: BSD-2-Clause-Patent\r
\r
**/\r
\r
#include "Tcg2Smm.h"\r
\r
-typedef enum {\r
- PtpInterfaceTis,\r
- PtpInterfaceFifo,\r
- PtpInterfaceCrb,\r
- PtpInterfaceMax,\r
-} PTP_INTERFACE_TYPE;\r
+EFI_SMM_VARIABLE_PROTOCOL *mSmmVariable = NULL;\r
+TCG_NVS *mTcgNvs = NULL;\r
+UINTN mPpSoftwareSmi;\r
+UINTN mMcSoftwareSmi;\r
+EFI_HANDLE mReadyToLockHandle;\r
\r
/**\r
- Return PTP interface type.\r
+ Communication service SMI Handler entry.\r
+\r
+ This handler takes requests to exchange Mmi channel and Nvs address between MM and DXE.\r
+\r
+ Caution: This function may receive untrusted input.\r
+ Communicate buffer and buffer size are external input, so this function will do basic validation.\r
+\r
+ @param[in] DispatchHandle The unique handle assigned to this handler by SmiHandlerRegister().\r
+ @param[in] RegisterContext Points to an optional handler context which was specified when the\r
+ handler was registered.\r
+ @param[in, out] CommBuffer A pointer to a collection of data in memory that will\r
+ be conveyed from a non-SMM environment into an SMM environment.\r
+ @param[in, out] CommBufferSize The size of the CommBuffer.\r
\r
- @param[in] Register Pointer to PTP register.\r
+ @retval EFI_SUCCESS The interrupt was handled and quiesced. No other handlers\r
+ should still be called.\r
+ @retval EFI_UNSUPPORTED An unknown test function was requested.\r
+ @retval EFI_ACCESS_DENIED Part of the communication buffer lies in an invalid region.\r
\r
- @return PTP interface type.\r
**/\r
-PTP_INTERFACE_TYPE\r
-GetPtpInterface (\r
- IN VOID *Register\r
+EFI_STATUS\r
+EFIAPI\r
+TpmNvsCommunciate (\r
+ IN EFI_HANDLE DispatchHandle,\r
+ IN CONST VOID *RegisterContext,\r
+ IN OUT VOID *CommBuffer,\r
+ IN OUT UINTN *CommBufferSize\r
)\r
{\r
- PTP_CRB_INTERFACE_IDENTIFIER InterfaceId;\r
- PTP_FIFO_INTERFACE_CAPABILITY InterfaceCapability;\r
+ EFI_STATUS Status;\r
+ UINTN TempCommBufferSize;\r
+ TPM_NVS_MM_COMM_BUFFER *CommParams;\r
+\r
+ DEBUG ((DEBUG_VERBOSE, "%a()\n", __FUNCTION__));\r
\r
//\r
- // Check interface id\r
+ // If input is invalid, stop processing this SMI\r
//\r
- InterfaceId.Uint32 = MmioRead32 ((UINTN)&((PTP_CRB_REGISTERS *)Register)->InterfaceId);\r
- InterfaceCapability.Uint32 = MmioRead32 ((UINTN)&((PTP_FIFO_REGISTERS *)Register)->InterfaceCapability);\r
-\r
- if (InterfaceId.Bits.InterfaceType == PTP_INTERFACE_IDENTIFIER_INTERFACE_TYPE_TIS) {\r
- return PtpInterfaceTis;\r
+ if ((CommBuffer == NULL) || (CommBufferSize == NULL)) {\r
+ return EFI_SUCCESS;\r
}\r
\r
- if ((InterfaceId.Bits.InterfaceType == PTP_INTERFACE_IDENTIFIER_INTERFACE_TYPE_CRB) &&\r
- (InterfaceId.Bits.InterfaceVersion == PTP_INTERFACE_IDENTIFIER_INTERFACE_VERSION_CRB) &&\r
- (InterfaceId.Bits.CapCRB != 0)) {\r
- return PtpInterfaceCrb;\r
+ TempCommBufferSize = *CommBufferSize;\r
+\r
+ if (TempCommBufferSize != sizeof (TPM_NVS_MM_COMM_BUFFER)) {\r
+ DEBUG ((DEBUG_ERROR, "[%a] MM Communication buffer size is invalid for this handler!\n", __FUNCTION__));\r
+ return EFI_ACCESS_DENIED;\r
}\r
\r
- if ((InterfaceId.Bits.InterfaceType == PTP_INTERFACE_IDENTIFIER_INTERFACE_TYPE_FIFO) &&\r
- (InterfaceId.Bits.InterfaceVersion == PTP_INTERFACE_IDENTIFIER_INTERFACE_VERSION_FIFO) &&\r
- (InterfaceId.Bits.CapFIFO != 0) &&\r
- (InterfaceCapability.Bits.InterfaceVersion == INTERFACE_CAPABILITY_INTERFACE_VERSION_PTP)) {\r
- return PtpInterfaceFifo;\r
+ if (!IsBufferOutsideMmValid ((UINTN)CommBuffer, TempCommBufferSize)) {\r
+ DEBUG ((DEBUG_ERROR, "[%a] - MM Communication buffer in invalid location!\n", __FUNCTION__));\r
+ return EFI_ACCESS_DENIED;\r
}\r
\r
//\r
- // No Ptp interface available\r
+ // Farm out the job to individual functions based on what was requested.\r
//\r
- return PtpInterfaceMax;\r
-}\r
+ CommParams = (TPM_NVS_MM_COMM_BUFFER *)CommBuffer;\r
+ Status = EFI_SUCCESS;\r
+ switch (CommParams->Function) {\r
+ case TpmNvsMmExchangeInfo:\r
+ DEBUG ((DEBUG_VERBOSE, "[%a] - Function requested: MM_EXCHANGE_NVS_INFO\n", __FUNCTION__));\r
+ CommParams->RegisteredPpSwiValue = mPpSoftwareSmi;\r
+ CommParams->RegisteredMcSwiValue = mMcSoftwareSmi;\r
+ mTcgNvs = (TCG_NVS *)(UINTN)CommParams->TargetAddress;\r
+ break;\r
\r
-EFI_TPM2_ACPI_TABLE mTpm2AcpiTemplate = {\r
- {\r
- EFI_ACPI_5_0_TRUSTED_COMPUTING_PLATFORM_2_TABLE_SIGNATURE,\r
- sizeof (mTpm2AcpiTemplate),\r
- EFI_TPM2_ACPI_TABLE_REVISION_4,\r
- //\r
- // Compiler initializes the remaining bytes to 0\r
- // These fields should be filled in in production\r
- //\r
- },\r
- 0, // 16-bit PlatformClass\r
- 0, // 16-bit Reserved\r
- 0, // Control Area\r
- EFI_TPM2_ACPI_TABLE_START_METHOD_TIS, // StartMethod\r
-};\r
-\r
-EFI_SMM_VARIABLE_PROTOCOL *mSmmVariable;\r
-TCG_NVS *mTcgNvs;\r
+ default:\r
+ DEBUG ((DEBUG_INFO, "[%a] - Unknown function %d!\n", __FUNCTION__, CommParams->Function));\r
+ Status = EFI_UNSUPPORTED;\r
+ break;\r
+ }\r
+\r
+ CommParams->ReturnStatus = (UINT64)Status;\r
+ return EFI_SUCCESS;\r
+}\r
\r
/**\r
Software SMI callback for TPM physical presence which is called from ACPI method.\r
EFI_STATUS\r
EFIAPI\r
PhysicalPresenceCallback (\r
- IN EFI_HANDLE DispatchHandle,\r
- IN CONST VOID *Context,\r
- IN OUT VOID *CommBuffer,\r
- IN OUT UINTN *CommBufferSize\r
+ IN EFI_HANDLE DispatchHandle,\r
+ IN CONST VOID *Context,\r
+ IN OUT VOID *CommBuffer,\r
+ IN OUT UINTN *CommBufferSize\r
)\r
{\r
- UINT32 MostRecentRequest;\r
- UINT32 Response;\r
- UINT32 OperationRequest;\r
- UINT32 RequestParameter;\r
-\r
+ UINT32 MostRecentRequest;\r
+ UINT32 Response;\r
+ UINT32 OperationRequest;\r
+ UINT32 RequestParameter;\r
\r
if (mTcgNvs->PhysicalPresence.Parameter == TCG_ACPI_FUNCTION_RETURN_REQUEST_RESPONSE_TO_OS) {\r
mTcgNvs->PhysicalPresence.ReturnCode = Tcg2PhysicalPresenceLibReturnOperationResponseToOsFunction (\r
&Response\r
);\r
mTcgNvs->PhysicalPresence.LastRequest = MostRecentRequest;\r
- mTcgNvs->PhysicalPresence.Response = Response;\r
+ mTcgNvs->PhysicalPresence.Response = Response;\r
return EFI_SUCCESS;\r
- } else if ((mTcgNvs->PhysicalPresence.Parameter == TCG_ACPI_FUNCTION_SUBMIT_REQUEST_TO_BIOS) \r
- || (mTcgNvs->PhysicalPresence.Parameter == TCG_ACPI_FUNCTION_SUBMIT_REQUEST_TO_BIOS_2)) {\r
-\r
- OperationRequest = mTcgNvs->PhysicalPresence.Request;\r
- RequestParameter = mTcgNvs->PhysicalPresence.RequestParameter;\r
+ } else if ( (mTcgNvs->PhysicalPresence.Parameter == TCG_ACPI_FUNCTION_SUBMIT_REQUEST_TO_BIOS)\r
+ || (mTcgNvs->PhysicalPresence.Parameter == TCG_ACPI_FUNCTION_SUBMIT_REQUEST_TO_BIOS_2))\r
+ {\r
+ OperationRequest = mTcgNvs->PhysicalPresence.Request;\r
+ RequestParameter = mTcgNvs->PhysicalPresence.RequestParameter;\r
mTcgNvs->PhysicalPresence.ReturnCode = Tcg2PhysicalPresenceLibSubmitRequestToPreOSFunctionEx (\r
&OperationRequest,\r
&RequestParameter\r
);\r
- mTcgNvs->PhysicalPresence.Request = OperationRequest;\r
+ mTcgNvs->PhysicalPresence.Request = OperationRequest;\r
mTcgNvs->PhysicalPresence.RequestParameter = RequestParameter;\r
} else if (mTcgNvs->PhysicalPresence.Parameter == TCG_ACPI_FUNCTION_GET_USER_CONFIRMATION_STATUS_FOR_REQUEST) {\r
mTcgNvs->PhysicalPresence.ReturnCode = Tcg2PhysicalPresenceLibGetUserConfirmationStatusFunction (mTcgNvs->PPRequestUserConfirm);\r
return EFI_SUCCESS;\r
}\r
\r
-\r
/**\r
Software SMI callback for MemoryClear which is called from ACPI method.\r
\r
EFI_STATUS\r
EFIAPI\r
MemoryClearCallback (\r
- IN EFI_HANDLE DispatchHandle,\r
- IN CONST VOID *Context,\r
- IN OUT VOID *CommBuffer,\r
- IN OUT UINTN *CommBufferSize\r
+ IN EFI_HANDLE DispatchHandle,\r
+ IN CONST VOID *Context,\r
+ IN OUT VOID *CommBuffer,\r
+ IN OUT UINTN *CommBufferSize\r
)\r
{\r
- EFI_STATUS Status;\r
- UINTN DataSize;\r
- UINT8 MorControl;\r
+ EFI_STATUS Status;\r
+ UINTN DataSize;\r
+ UINT8 MorControl;\r
\r
mTcgNvs->MemoryClear.ReturnCode = MOR_REQUEST_SUCCESS;\r
if (mTcgNvs->MemoryClear.Parameter == ACPI_FUNCTION_DSM_MEMORY_CLEAR_INTERFACE) {\r
- MorControl = (UINT8) mTcgNvs->MemoryClear.Request;\r
+ MorControl = (UINT8)mTcgNvs->MemoryClear.Request;\r
} else if (mTcgNvs->MemoryClear.Parameter == ACPI_FUNCTION_PTS_CLEAR_MOR_BIT) {\r
DataSize = sizeof (UINT8);\r
- Status = mSmmVariable->SmmGetVariable (\r
- MEMORY_OVERWRITE_REQUEST_VARIABLE_NAME,\r
- &gEfiMemoryOverwriteControlDataGuid,\r
- NULL,\r
- &DataSize,\r
- &MorControl\r
- );\r
+ Status = mSmmVariable->SmmGetVariable (\r
+ MEMORY_OVERWRITE_REQUEST_VARIABLE_NAME,\r
+ &gEfiMemoryOverwriteControlDataGuid,\r
+ NULL,\r
+ &DataSize,\r
+ &MorControl\r
+ );\r
if (EFI_ERROR (Status)) {\r
mTcgNvs->MemoryClear.ReturnCode = MOR_REQUEST_GENERAL_FAILURE;\r
- DEBUG ((EFI_D_ERROR, "[TPM] Get MOR variable failure! Status = %r\n", Status));\r
+ DEBUG ((DEBUG_ERROR, "[TPM] Get MOR variable failure! Status = %r\n", Status));\r
return EFI_SUCCESS;\r
}\r
\r
if (MOR_CLEAR_MEMORY_VALUE (MorControl) == 0x0) {\r
return EFI_SUCCESS;\r
}\r
+\r
MorControl &= ~MOR_CLEAR_MEMORY_BIT_MASK;\r
+ } else {\r
+ mTcgNvs->MemoryClear.ReturnCode = MOR_REQUEST_GENERAL_FAILURE;\r
+ DEBUG ((DEBUG_ERROR, "[TPM] MOR Parameter error! Parameter = %x\n", mTcgNvs->MemoryClear.Parameter));\r
+ return EFI_SUCCESS;\r
}\r
\r
DataSize = sizeof (UINT8);\r
- Status = mSmmVariable->SmmSetVariable (\r
- MEMORY_OVERWRITE_REQUEST_VARIABLE_NAME,\r
- &gEfiMemoryOverwriteControlDataGuid,\r
- EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,\r
- DataSize,\r
- &MorControl\r
- );\r
- if (EFI_ERROR (Status)) { \r
+ Status = mSmmVariable->SmmSetVariable (\r
+ MEMORY_OVERWRITE_REQUEST_VARIABLE_NAME,\r
+ &gEfiMemoryOverwriteControlDataGuid,\r
+ EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,\r
+ DataSize,\r
+ &MorControl\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
mTcgNvs->MemoryClear.ReturnCode = MOR_REQUEST_GENERAL_FAILURE;\r
- DEBUG ((EFI_D_ERROR, "[TPM] Set MOR variable failure! Status = %r\n", Status));\r
+ DEBUG ((DEBUG_ERROR, "[TPM] Set MOR variable failure! Status = %r\n", Status));\r
}\r
\r
return EFI_SUCCESS;\r
}\r
\r
/**\r
- Find the operation region in TCG ACPI table by given Name and Size,\r
- and initialize it if the region is found.\r
+ Notification for SMM ReadyToLock protocol.\r
\r
- @param[in, out] Table The TPM item in ACPI table.\r
- @param[in] Name The name string to find in TPM table.\r
- @param[in] Size The size of the region to find.\r
+ @param[in] Protocol Points to the protocol's unique identifier.\r
+ @param[in] Interface Points to the interface instance.\r
+ @param[in] Handle The handle on which the interface was installed.\r
\r
- @return The allocated address for the found region.\r
-\r
-**/\r
-VOID *\r
-AssignOpRegion (\r
- EFI_ACPI_DESCRIPTION_HEADER *Table,\r
- UINT32 Name,\r
- UINT16 Size\r
- )\r
-{\r
- EFI_STATUS Status;\r
- AML_OP_REGION_32_8 *OpRegion;\r
- EFI_PHYSICAL_ADDRESS MemoryAddress;\r
-\r
- MemoryAddress = SIZE_4GB - 1;\r
-\r
- //\r
- // Patch some pointers for the ASL code before loading the SSDT.\r
- //\r
- for (OpRegion = (AML_OP_REGION_32_8 *) (Table + 1);\r
- OpRegion <= (AML_OP_REGION_32_8 *) ((UINT8 *) Table + Table->Length);\r
- OpRegion = (AML_OP_REGION_32_8 *) ((UINT8 *) OpRegion + 1)) {\r
- if ((OpRegion->OpRegionOp == AML_EXT_REGION_OP) && \r
- (OpRegion->NameString == Name) &&\r
- (OpRegion->DWordPrefix == AML_DWORD_PREFIX) &&\r
- (OpRegion->BytePrefix == AML_BYTE_PREFIX)) {\r
-\r
- Status = gBS->AllocatePages(AllocateMaxAddress, EfiACPIMemoryNVS, EFI_SIZE_TO_PAGES (Size), &MemoryAddress);\r
- ASSERT_EFI_ERROR (Status);\r
- ZeroMem ((VOID *)(UINTN)MemoryAddress, Size);\r
- OpRegion->RegionOffset = (UINT32) (UINTN) MemoryAddress;\r
- OpRegion->RegionLen = (UINT8) Size;\r
- break;\r
- }\r
- }\r
-\r
- return (VOID *) (UINTN) MemoryAddress;\r
-}\r
-\r
-/**\r
- Patch version string of Physical Presence interface supported by platform. The initial string tag in TPM \r
-ACPI table is "$PV".\r
-\r
- @param[in, out] Table The TPM item in ACPI table.\r
- @param[in] PPVer Version string of Physical Presence interface supported by platform.\r
-\r
- @return The allocated address for the found region.\r
-\r
-**/\r
-EFI_STATUS\r
-UpdatePPVersion (\r
- EFI_ACPI_DESCRIPTION_HEADER *Table,\r
- CHAR8 *PPVer\r
- )\r
-{\r
- EFI_STATUS Status;\r
- UINT8 *DataPtr;\r
-\r
- //\r
- // Patch some pointers for the ASL code before loading the SSDT.\r
- //\r
- for (DataPtr = (UINT8 *)(Table + 1);\r
- DataPtr <= (UINT8 *) ((UINT8 *) Table + Table->Length - PHYSICAL_PRESENCE_VERSION_SIZE);\r
- DataPtr += 1) {\r
- if (AsciiStrCmp((CHAR8 *)DataPtr, PHYSICAL_PRESENCE_VERSION_TAG) == 0) {\r
- Status = AsciiStrCpyS((CHAR8 *)DataPtr, PHYSICAL_PRESENCE_VERSION_SIZE, PPVer);\r
- DEBUG((EFI_D_INFO, "TPM2 Physical Presence Interface Version update status 0x%x\n", Status));\r
- return Status;\r
- }\r
- }\r
-\r
- return EFI_NOT_FOUND;\r
-}\r
-\r
-/**\r
- Patch TPM2 device HID string. The initial string tag in TPM2 ACPI table is "NNN0000".\r
-\r
- @param[in, out] Table The TPM2 SSDT ACPI table.\r
-\r
- @return HID Update status.\r
+ @retval EFI_SUCCESS Notification runs successfully.\r
\r
**/\r
EFI_STATUS\r
-UpdateHID (\r
- EFI_ACPI_DESCRIPTION_HEADER *Table\r
+EFIAPI\r
+TcgMmReadyToLock (\r
+ IN CONST EFI_GUID *Protocol,\r
+ IN VOID *Interface,\r
+ IN EFI_HANDLE Handle\r
)\r
{\r
EFI_STATUS Status;\r
- UINT8 *DataPtr;\r
- CHAR8 Hid[TPM_HID_ACPI_SIZE];\r
- UINT32 ManufacturerID;\r
- UINT32 FirmwareVersion1;\r
- UINT32 FirmwareVersion2;\r
- BOOLEAN PnpHID;\r
-\r
- PnpHID = TRUE;\r
-\r
- //\r
- // Initialize HID with Default PNP string\r
- //\r
- ZeroMem(Hid, TPM_HID_ACPI_SIZE);\r
-\r
- //\r
- // Get Manufacturer ID\r
- //\r
- Status = Tpm2GetCapabilityManufactureID(&ManufacturerID);\r
- if (!EFI_ERROR(Status)) {\r
- DEBUG((EFI_D_INFO, "TPM_PT_MANUFACTURER 0x%08x\n", ManufacturerID));\r
- //\r
- // ManufacturerID defined in TCG Vendor ID Registry \r
- // may tailed with 0x00 or 0x20\r
- //\r
- if ((ManufacturerID >> 24) == 0x00 || ((ManufacturerID >> 24) == 0x20)) {\r
- //\r
- // HID containing PNP ID "NNN####"\r
- // NNN is uppercase letter for Vendor ID specified by manufacturer\r
- //\r
- CopyMem(Hid, &ManufacturerID, 3);\r
- } else {\r
- //\r
- // HID containing ACP ID "NNNN####"\r
- // NNNN is uppercase letter for Vendor ID specified by manufacturer\r
- //\r
- CopyMem(Hid, &ManufacturerID, 4);\r
- PnpHID = FALSE;\r
- }\r
- } else {\r
- DEBUG ((EFI_D_ERROR, "Get TPM_PT_MANUFACTURER failed %x!\n", Status));\r
- ASSERT(FALSE);\r
- return Status;\r
- }\r
-\r
- Status = Tpm2GetCapabilityFirmwareVersion(&FirmwareVersion1, &FirmwareVersion2);\r
- if (!EFI_ERROR(Status)) {\r
- DEBUG((EFI_D_INFO, "TPM_PT_FIRMWARE_VERSION_1 0x%x\n", FirmwareVersion1));\r
- DEBUG((EFI_D_INFO, "TPM_PT_FIRMWARE_VERSION_2 0x%x\n", FirmwareVersion2));\r
- //\r
- // #### is Firmware Version 1\r
- //\r
- if (PnpHID) {\r
- AsciiSPrint(Hid + 3, TPM_HID_PNP_SIZE - 3, "%02d%02d", ((FirmwareVersion1 & 0xFFFF0000) >> 16), (FirmwareVersion1 && 0x0000FFFF));\r
- } else {\r
- AsciiSPrint(Hid + 4, TPM_HID_ACPI_SIZE - 4, "%02d%02d", ((FirmwareVersion1 & 0xFFFF0000) >> 16), (FirmwareVersion1 && 0x0000FFFF));\r
- }\r
- \r
- } else {\r
- DEBUG ((EFI_D_ERROR, "Get TPM_PT_FIRMWARE_VERSION_X failed %x!\n", Status));\r
- ASSERT(FALSE);\r
- return Status;\r
- }\r
-\r
- //\r
- // Patch HID in ASL code before loading the SSDT.\r
- //\r
- for (DataPtr = (UINT8 *)(Table + 1);\r
- DataPtr <= (UINT8 *) ((UINT8 *) Table + Table->Length - TPM_HID_PNP_SIZE);\r
- DataPtr += 1) {\r
- if (AsciiStrCmp((CHAR8 *)DataPtr, TPM_HID_TAG) == 0) {\r
- if (PnpHID) {\r
- CopyMem(DataPtr, Hid, TPM_HID_PNP_SIZE);\r
- //\r
- // if HID is PNP ID, patch the last byte in HID TAG to Noop\r
- //\r
- *(DataPtr + TPM_HID_PNP_SIZE) = AML_NOOP_OP;\r
- } else {\r
-\r
- CopyMem(DataPtr, Hid, TPM_HID_ACPI_SIZE);\r
- }\r
- DEBUG((DEBUG_INFO, "TPM2 ACPI _HID is patched to %a\n", DataPtr));\r
-\r
- return Status;\r
- }\r
- }\r
-\r
- DEBUG((EFI_D_ERROR, "TPM2 ACPI HID TAG for patch not found!\n"));\r
- return EFI_NOT_FOUND;\r
-}\r
\r
-/**\r
- Initialize and publish TPM items in ACPI table.\r
-\r
- @retval EFI_SUCCESS The TCG ACPI table is published successfully.\r
- @retval Others The TCG ACPI table is not published.\r
+ Status = EFI_SUCCESS;\r
\r
-**/\r
-EFI_STATUS\r
-PublishAcpiTable (\r
- VOID\r
- )\r
-{\r
- EFI_STATUS Status;\r
- EFI_ACPI_TABLE_PROTOCOL *AcpiTable;\r
- UINTN TableKey;\r
- EFI_ACPI_DESCRIPTION_HEADER *Table;\r
- UINTN TableSize;\r
-\r
- Status = GetSectionFromFv (\r
- &gEfiCallerIdGuid,\r
- EFI_SECTION_RAW,\r
- 0,\r
- (VOID **) &Table,\r
- &TableSize\r
- );\r
- ASSERT_EFI_ERROR (Status);\r
-\r
- //\r
- // Update Table version before measuring it to PCR\r
- //\r
- Status = UpdatePPVersion(Table, (CHAR8 *)PcdGetPtr(PcdTcgPhysicalPresenceInterfaceVer));\r
- ASSERT_EFI_ERROR (Status);\r
-\r
- DEBUG ((\r
- DEBUG_INFO,\r
- "Current physical presence interface version - %a\n",\r
- (CHAR8 *) PcdGetPtr(PcdTcgPhysicalPresenceInterfaceVer)\r
- ));\r
-\r
- //\r
- // Update TPM2 HID before measuring it to PCR\r
- //\r
- Status = UpdateHID(Table);\r
- if (EFI_ERROR(Status)) {\r
- return Status;\r
+ if (mReadyToLockHandle != NULL) {\r
+ Status = gMmst->MmiHandlerUnRegister (mReadyToLockHandle);\r
+ mReadyToLockHandle = NULL;\r
}\r
\r
- //\r
- // Measure to PCR[0] with event EV_POST_CODE ACPI DATA\r
- //\r
- TpmMeasureAndLogData(\r
- 0,\r
- EV_POST_CODE,\r
- EV_POSTCODE_INFO_ACPI_DATA,\r
- ACPI_DATA_LEN,\r
- Table,\r
- TableSize\r
- );\r
-\r
-\r
- ASSERT (Table->OemTableId == SIGNATURE_64 ('T', 'p', 'm', '2', 'T', 'a', 'b', 'l'));\r
- CopyMem (Table->OemId, PcdGetPtr (PcdAcpiDefaultOemId), sizeof (Table->OemId) );\r
- mTcgNvs = AssignOpRegion (Table, SIGNATURE_32 ('T', 'N', 'V', 'S'), (UINT16) sizeof (TCG_NVS));\r
- ASSERT (mTcgNvs != NULL);\r
-\r
- //\r
- // Publish the TPM ACPI table. Table is re-checksumed.\r
- //\r
- Status = gBS->LocateProtocol (&gEfiAcpiTableProtocolGuid, NULL, (VOID **) &AcpiTable);\r
- ASSERT_EFI_ERROR (Status);\r
-\r
- TableKey = 0;\r
- Status = AcpiTable->InstallAcpiTable (\r
- AcpiTable,\r
- Table,\r
- TableSize,\r
- &TableKey\r
- );\r
- ASSERT_EFI_ERROR (Status);\r
-\r
return Status;\r
}\r
\r
/**\r
- Publish TPM2 ACPI table\r
+ The driver's common initialization routine.\r
\r
- @retval EFI_SUCCESS The TPM2 ACPI table is published successfully.\r
- @retval Others The TPM2 ACPI table is not published.\r
-\r
-**/\r
-EFI_STATUS\r
-PublishTpm2 (\r
- VOID\r
- )\r
-{\r
- EFI_STATUS Status;\r
- EFI_ACPI_TABLE_PROTOCOL *AcpiTable;\r
- UINTN TableKey;\r
- UINT64 OemTableId;\r
- EFI_TPM2_ACPI_CONTROL_AREA *ControlArea;\r
- PTP_INTERFACE_TYPE InterfaceType;\r
-\r
- mTpm2AcpiTemplate.Header.Revision = PcdGet8(PcdTpm2AcpiTableRev);\r
- DEBUG((DEBUG_INFO, "Tpm2 ACPI table revision is %d\n", mTpm2AcpiTemplate.Header.Revision));\r
-\r
- //\r
- // Measure to PCR[0] with event EV_POST_CODE ACPI DATA\r
- //\r
- TpmMeasureAndLogData(\r
- 0,\r
- EV_POST_CODE,\r
- EV_POSTCODE_INFO_ACPI_DATA,\r
- ACPI_DATA_LEN,\r
- &mTpm2AcpiTemplate,\r
- sizeof(mTpm2AcpiTemplate)\r
- );\r
-\r
- InterfaceType = GetPtpInterface ((VOID *) (UINTN) PcdGet64 (PcdTpmBaseAddress));\r
- switch (InterfaceType) {\r
- case PtpInterfaceCrb:\r
- mTpm2AcpiTemplate.StartMethod = EFI_TPM2_ACPI_TABLE_START_METHOD_COMMAND_RESPONSE_BUFFER_INTERFACE;\r
- mTpm2AcpiTemplate.AddressOfControlArea = PcdGet64 (PcdTpmBaseAddress) + 0x40;\r
- ControlArea = (EFI_TPM2_ACPI_CONTROL_AREA *)(UINTN)mTpm2AcpiTemplate.AddressOfControlArea;\r
- ControlArea->CommandSize = 0xF80;\r
- ControlArea->ResponseSize = 0xF80;\r
- ControlArea->Command = PcdGet64 (PcdTpmBaseAddress) + 0x80;\r
- ControlArea->Response = PcdGet64 (PcdTpmBaseAddress) + 0x80;\r
- break;\r
- case PtpInterfaceFifo:\r
- case PtpInterfaceTis:\r
- break;\r
- default:\r
- DEBUG((EFI_D_ERROR, "TPM2 InterfaceType get error! %d\n", InterfaceType));\r
- break;\r
- }\r
-\r
- CopyMem (mTpm2AcpiTemplate.Header.OemId, PcdGetPtr (PcdAcpiDefaultOemId), sizeof (mTpm2AcpiTemplate.Header.OemId));\r
- OemTableId = PcdGet64 (PcdAcpiDefaultOemTableId);\r
- CopyMem (&mTpm2AcpiTemplate.Header.OemTableId, &OemTableId, sizeof (UINT64));\r
- mTpm2AcpiTemplate.Header.OemRevision = PcdGet32 (PcdAcpiDefaultOemRevision);\r
- mTpm2AcpiTemplate.Header.CreatorId = PcdGet32 (PcdAcpiDefaultCreatorId);\r
- mTpm2AcpiTemplate.Header.CreatorRevision = PcdGet32 (PcdAcpiDefaultCreatorRevision);\r
-\r
- //\r
- // Construct ACPI table\r
- //\r
- Status = gBS->LocateProtocol (&gEfiAcpiTableProtocolGuid, NULL, (VOID **) &AcpiTable);\r
- ASSERT_EFI_ERROR (Status);\r
-\r
- Status = AcpiTable->InstallAcpiTable (\r
- AcpiTable,\r
- &mTpm2AcpiTemplate,\r
- sizeof(mTpm2AcpiTemplate),\r
- &TableKey\r
- );\r
- ASSERT_EFI_ERROR (Status);\r
-\r
- return Status;\r
-}\r
-\r
-/**\r
- The driver's entry point.\r
-\r
- It install callbacks for TPM physical presence and MemoryClear, and locate \r
+ It install callbacks for TPM physical presence and MemoryClear, and locate\r
SMM variable to be used in the callback function.\r
\r
- @param[in] ImageHandle The firmware allocated handle for the EFI image. \r
- @param[in] SystemTable A pointer to the EFI System Table.\r
- \r
@retval EFI_SUCCESS The entry point is executed successfully.\r
@retval Others Some error occurs when executing this entry point.\r
\r
**/\r
EFI_STATUS\r
-EFIAPI\r
-InitializeTcgSmm (\r
- IN EFI_HANDLE ImageHandle,\r
- IN EFI_SYSTEM_TABLE *SystemTable\r
+InitializeTcgCommon (\r
+ VOID\r
)\r
{\r
EFI_STATUS Status;\r
EFI_SMM_SW_DISPATCH2_PROTOCOL *SwDispatch;\r
EFI_SMM_SW_REGISTER_CONTEXT SwContext;\r
- EFI_HANDLE SwHandle;\r
+ EFI_HANDLE PpSwHandle;\r
+ EFI_HANDLE McSwHandle;\r
+ EFI_HANDLE NotifyHandle;\r
\r
- if (!CompareGuid (PcdGetPtr(PcdTpmInstanceGuid), &gEfiTpmDeviceInstanceTpm20DtpmGuid)){\r
- DEBUG ((EFI_D_ERROR, "No TPM2 DTPM instance required!\n"));\r
+ if (!CompareGuid (PcdGetPtr (PcdTpmInstanceGuid), &gEfiTpmDeviceInstanceTpm20DtpmGuid)) {\r
+ DEBUG ((DEBUG_ERROR, "No TPM2 DTPM instance required!\n"));\r
return EFI_UNSUPPORTED;\r
}\r
\r
- Status = PublishAcpiTable ();\r
+ // Initialize variables first\r
+ mReadyToLockHandle = NULL;\r
+ SwDispatch = NULL;\r
+ PpSwHandle = NULL;\r
+ McSwHandle = NULL;\r
+ NotifyHandle = NULL;\r
+\r
+ // Register a root handler to communicate the NVS region and SMI channel between MM and DXE\r
+ Status = gMmst->MmiHandlerRegister (TpmNvsCommunciate, &gTpmNvsMmGuid, &mReadyToLockHandle);\r
ASSERT_EFI_ERROR (Status);\r
+ if (EFI_ERROR (Status)) {\r
+ DEBUG ((DEBUG_ERROR, "[%a] Failed to register NVS communicate as root MM handler - %r!\n", __FUNCTION__, Status));\r
+ goto Cleanup;\r
+ }\r
\r
//\r
// Get the Sw dispatch protocol and register SMI callback functions.\r
//\r
- Status = gSmst->SmmLocateProtocol (&gEfiSmmSwDispatch2ProtocolGuid, NULL, (VOID**)&SwDispatch);\r
+ Status = gMmst->MmLocateProtocol (&gEfiSmmSwDispatch2ProtocolGuid, NULL, (VOID **)&SwDispatch);\r
ASSERT_EFI_ERROR (Status);\r
- SwContext.SwSmiInputValue = (UINTN) -1;\r
- Status = SwDispatch->Register (SwDispatch, PhysicalPresenceCallback, &SwContext, &SwHandle);\r
+ if (EFI_ERROR (Status)) {\r
+ DEBUG ((DEBUG_ERROR, "[%a] Failed to locate Sw dispatch protocol - %r!\n", __FUNCTION__, Status));\r
+ goto Cleanup;\r
+ }\r
+\r
+ SwContext.SwSmiInputValue = (UINTN)-1;\r
+ Status = SwDispatch->Register (SwDispatch, PhysicalPresenceCallback, &SwContext, &PpSwHandle);\r
ASSERT_EFI_ERROR (Status);\r
if (EFI_ERROR (Status)) {\r
- return Status;\r
+ DEBUG ((DEBUG_ERROR, "[%a] Failed to register PP callback as SW MM handler - %r!\n", __FUNCTION__, Status));\r
+ goto Cleanup;\r
}\r
- mTcgNvs->PhysicalPresence.SoftwareSmi = (UINT8) SwContext.SwSmiInputValue;\r
\r
- SwContext.SwSmiInputValue = (UINTN) -1;\r
- Status = SwDispatch->Register (SwDispatch, MemoryClearCallback, &SwContext, &SwHandle);\r
+ mPpSoftwareSmi = SwContext.SwSmiInputValue;\r
+\r
+ SwContext.SwSmiInputValue = (UINTN)-1;\r
+ Status = SwDispatch->Register (SwDispatch, MemoryClearCallback, &SwContext, &McSwHandle);\r
ASSERT_EFI_ERROR (Status);\r
if (EFI_ERROR (Status)) {\r
- return Status;\r
+ DEBUG ((DEBUG_ERROR, "[%a] Failed to register MC callback as SW MM handler - %r!\n", __FUNCTION__, Status));\r
+ goto Cleanup;\r
}\r
- mTcgNvs->MemoryClear.SoftwareSmi = (UINT8) SwContext.SwSmiInputValue;\r
- \r
+\r
+ mMcSoftwareSmi = SwContext.SwSmiInputValue;\r
+\r
//\r
// Locate SmmVariableProtocol.\r
//\r
- Status = gSmst->SmmLocateProtocol (&gEfiSmmVariableProtocolGuid, NULL, (VOID**)&mSmmVariable);\r
+ Status = gMmst->MmLocateProtocol (&gEfiSmmVariableProtocolGuid, NULL, (VOID **)&mSmmVariable);\r
ASSERT_EFI_ERROR (Status);\r
+ if (EFI_ERROR (Status)) {\r
+ // Should not happen\r
+ DEBUG ((DEBUG_ERROR, "[%a] Failed to locate SMM variable protocol - %r!\n", __FUNCTION__, Status));\r
+ goto Cleanup;\r
+ }\r
\r
- //\r
- // Set TPM2 ACPI table\r
- //\r
- Status = PublishTpm2 ();\r
+ // Turn off the light before leaving the room... at least, take a remote...\r
+ Status = gMmst->MmRegisterProtocolNotify (&gEfiMmReadyToLockProtocolGuid, TcgMmReadyToLock, &NotifyHandle);\r
ASSERT_EFI_ERROR (Status);\r
+ if (EFI_ERROR (Status)) {\r
+ DEBUG ((DEBUG_ERROR, "[%a] Failed to register ready to lock notification - %r!\n", __FUNCTION__, Status));\r
+ goto Cleanup;\r
+ }\r
\r
+ Tcg2NotifyMmReady ();\r
\r
- return EFI_SUCCESS;\r
-}\r
+Cleanup:\r
+ if (EFI_ERROR (Status)) {\r
+ // Something is whacked, clean up the mess...\r
+ if (NotifyHandle != NULL) {\r
+ gMmst->MmRegisterProtocolNotify (&gEfiMmReadyToLockProtocolGuid, NULL, &NotifyHandle);\r
+ }\r
+\r
+ if ((McSwHandle != NULL) && (SwDispatch != NULL)) {\r
+ SwDispatch->UnRegister (SwDispatch, McSwHandle);\r
+ }\r
+\r
+ if ((PpSwHandle != NULL) && (SwDispatch != NULL)) {\r
+ SwDispatch->UnRegister (SwDispatch, PpSwHandle);\r
+ }\r
\r
+ if (mReadyToLockHandle != NULL) {\r
+ gMmst->MmiHandlerUnRegister (mReadyToLockHandle);\r
+ }\r
+ }\r
+\r
+ return Status;\r
+}\r