PhysicalPresenceCallback() and MemoryClearCallback() will receive untrusted input and do some check.\r
\r
Copyright (c) 2015 - 2018, 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
+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
-\r
-/**\r
- Return PTP interface type.\r
+#pragma pack(1)\r
\r
- @param[in] Register Pointer to PTP register.\r
-\r
- @return PTP interface type.\r
-**/\r
-PTP_INTERFACE_TYPE\r
-GetPtpInterface (\r
- IN VOID *Register\r
- )\r
-{\r
- PTP_CRB_INTERFACE_IDENTIFIER InterfaceId;\r
- PTP_FIFO_INTERFACE_CAPABILITY InterfaceCapability;\r
-\r
- //\r
- // Check interface id\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
- }\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
- }\r
+typedef struct {\r
+ EFI_ACPI_DESCRIPTION_HEADER Header;\r
+ // Flags field is replaced in version 4 and above\r
+ // BIT0~15: PlatformClass This field is only valid for version 4 and above\r
+ // BIT16~31: Reserved\r
+ UINT32 Flags;\r
+ UINT64 AddressOfControlArea;\r
+ UINT32 StartMethod;\r
+ UINT8 PlatformSpecificParameters[12]; // size up to 12\r
+ UINT32 Laml; // Optional\r
+ UINT64 Lasa; // Optional\r
+} EFI_TPM2_ACPI_TABLE_V4;\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
- }\r
+#pragma pack()\r
\r
- //\r
- // No Ptp interface available\r
- //\r
- return PtpInterfaceMax;\r
-}\r
-\r
-EFI_TPM2_ACPI_TABLE mTpm2AcpiTemplate = {\r
+EFI_TPM2_ACPI_TABLE_V4 mTpm2AcpiTemplate = {\r
{\r
EFI_ACPI_5_0_TRUSTED_COMPUTING_PLATFORM_2_TABLE_SIGNATURE,\r
sizeof (mTpm2AcpiTemplate),\r
mTcgNvs->PhysicalPresence.LastRequest = MostRecentRequest;\r
mTcgNvs->PhysicalPresence.Response = Response;\r
return EFI_SUCCESS;\r
- } else if ((mTcgNvs->PhysicalPresence.Parameter == TCG_ACPI_FUNCTION_SUBMIT_REQUEST_TO_BIOS) \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
return EFI_SUCCESS;\r
}\r
MorControl &= ~MOR_CLEAR_MEMORY_BIT_MASK;\r
+ } else {\r
+ mTcgNvs->MemoryClear.ReturnCode = MOR_REQUEST_GENERAL_FAILURE;\r
+ DEBUG ((EFI_D_ERROR, "[TPM] MOR Parameter error! Parameter = %x\n", mTcgNvs->MemoryClear.Parameter));\r
+ return EFI_SUCCESS;\r
}\r
\r
DataSize = sizeof (UINT8);\r
DataSize,\r
&MorControl\r
);\r
- if (EFI_ERROR (Status)) { \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
}\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
+ 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
\r
/**\r
- Patch version string of Physical Presence interface supported by platform. The initial string tag in TPM \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
\r
/**\r
Patch interrupt resources returned by TPM _PRS. ResourceTemplate to patch is determined by input\r
- interrupt buffer size. BufferSize, PkgLength and interrupt descirptor in ByteList need to be patched\r
+ interrupt buffer size. BufferSize, PkgLength and interrupt descriptor in ByteList need to be patched\r
\r
@param[in, out] Table The TPM item in ACPI table.\r
@param[in] IrqBuffer Input new IRQ buffer.\r
@param[in] IrqBuffserSize Input new IRQ buffer size.\r
+ @param[out] IsShortFormPkgLength If _PRS returns Short length Package(ACPI spec 20.2.4).\r
\r
@return patch status.\r
\r
**/\r
EFI_STATUS\r
UpdatePossibleResource (\r
- EFI_ACPI_DESCRIPTION_HEADER *Table,\r
- UINT32 *IrqBuffer,\r
- UINT32 IrqBuffserSize\r
+ IN OUT EFI_ACPI_DESCRIPTION_HEADER *Table,\r
+ IN UINT32 *IrqBuffer,\r
+ IN UINT32 IrqBuffserSize,\r
+ OUT BOOLEAN *IsShortFormPkgLength\r
)\r
{\r
UINT8 *DataPtr;\r
// to patch TPM ACPI object _PRS returned ResourceTemplate() containing 2 resource descriptors and an auto appended End Tag\r
//\r
// AML data is organized by following rule.\r
- // Code need to patch BufferSize and PkgLength and interrupt descirptor in ByteList\r
+ // Code need to patch BufferSize and PkgLength and interrupt descriptor in ByteList\r
//\r
// ============= Buffer ====================\r
// DefBuffer := BufferOp PkgLength BufferSize ByteList\r
// <bit 3-0: Least significant package length nybble>\r
//\r
//==============BufferSize==================\r
- // BufferSize := Integar\r
- // Integar := ByteConst|WordConst|DwordConst....\r
+ // BufferSize := Integer\r
+ // Integer := ByteConst|WordConst|DwordConst....\r
//\r
// ByteConst := BytePrefix ByteData\r
//\r
}\r
\r
//\r
- // Include Memory32Fixed Descritor (12 Bytes) + Interrupt Descriptor header(5 Bytes) + End Tag(2 Bytes)\r
+ // Include Memory32Fixed Descriptor (12 Bytes) + Interrupt Descriptor header(5 Bytes) + End Tag(2 Bytes)\r
//\r
NewPkgLength += 19 + IrqBuffserSize;\r
if (NewPkgLength > 63) {\r
*DataPtr = (UINT8)NewPkgLength;\r
\r
//\r
- // 1.2 Patch BufferSize = sizeof(Memory32Fixed Descritor + Interrupt Descriptor + End Tag).\r
+ // 1.2 Patch BufferSize = sizeof(Memory32Fixed Descriptor + Interrupt Descriptor + End Tag).\r
// It is Little endian. So only patch lowest byte of BufferSize due to current interrupt number limit.\r
//\r
*(DataPtr + 2) = (UINT8)(IrqBuffserSize + 19);\r
//\r
// Notify _PRS to report short formed ResourceTemplate\r
//\r
- mTcgNvs->IsShortFormPkgLength = TRUE;\r
+ *IsShortFormPkgLength = TRUE;\r
\r
break;\r
}\r
}\r
\r
//\r
- // Include Memory32Fixed Descritor (12 Bytes) + Interrupt Descriptor header(5 Bytes) + End Tag(2 Bytes)\r
+ // Include Memory32Fixed Descriptor (12 Bytes) + Interrupt Descriptor header(5 Bytes) + End Tag(2 Bytes)\r
//\r
NewPkgLength += 19 + IrqBuffserSize;\r
\r
*(DataPtr + 1) = (UINT8)((NewPkgLength & 0xFF0) >> 4);\r
\r
//\r
- // 2.2 Patch BufferSize = sizeof(Memory32Fixed Descritor + Interrupt Descriptor + End Tag).\r
+ // 2.2 Patch BufferSize = sizeof(Memory32Fixed Descriptor + Interrupt Descriptor + End Tag).\r
// It is Little endian. Only patch lowest byte of BufferSize due to current interrupt number limit.\r
//\r
*(DataPtr + 2 + ((*DataPtr & (BIT7|BIT6)) >> 6)) = (UINT8)(IrqBuffserSize + 19);\r
//\r
// Notify _PRS to report long formed ResourceTemplate\r
//\r
- mTcgNvs->IsShortFormPkgLength = FALSE;\r
+ *IsShortFormPkgLength = FALSE;\r
break;\r
}\r
}\r
//\r
DataPtr += NewPkgLength - (5 + IrqBuffserSize + 2);\r
//\r
- // 3.1 Patch Length bit[7:0] of Interrupt descirptor patch interrupt descriptor\r
+ // 3.1 Patch Length bit[7:0] of Interrupt descriptor patch interrupt descriptor\r
//\r
*(DataPtr + 1) = (UINT8)(2 + IrqBuffserSize);\r
//\r
CopyMem(DataPtr + 5, IrqBuffer, IrqBuffserSize);\r
\r
//\r
- // 4. Jump over Interrupt descirptor and Patch END Tag, set Checksum field to 0\r
+ // 4. Jump over Interrupt descriptor and Patch END Tag, set Checksum field to 0\r
//\r
DataPtr += 5 + IrqBuffserSize;\r
*DataPtr = ACPI_END_TAG_DESCRIPTOR;\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
+ // ManufacturerID defined in TCG Vendor ID Registry\r
// may tailed with 0x00 or 0x20\r
//\r
if ((ManufacturerID >> 24) == 0x00 || ((ManufacturerID >> 24) == 0x20)) {\r
} else {\r
AsciiSPrint(Hid + 4, TPM_HID_ACPI_SIZE - 4, "%02d%02d", ((FirmwareVersion1 & 0xFFFF0000) >> 16), (FirmwareVersion1 & 0x0000FFFF));\r
}\r
- \r
+\r
} else {\r
DEBUG ((EFI_D_ERROR, "Get TPM_PT_FIRMWARE_VERSION_X failed %x!\n", Status));\r
ASSERT(FALSE);\r
UINTN TableSize;\r
UINT32 *PossibleIrqNumBuf;\r
UINT32 PossibleIrqNumBufSize;\r
+ BOOLEAN IsShortFormPkgLength;\r
+\r
+ IsShortFormPkgLength = FALSE;\r
\r
Status = GetSectionFromFv (\r
&gEfiCallerIdGuid,\r
PossibleIrqNumBufSize = (UINT32)PcdGetSize(PcdTpm2PossibleIrqNumBuf);\r
\r
if (PossibleIrqNumBufSize <= MAX_PRS_INT_BUF_SIZE && (PossibleIrqNumBufSize % sizeof(UINT32)) == 0) {\r
- Status = UpdatePossibleResource(Table, PossibleIrqNumBuf, PossibleIrqNumBufSize);\r
+ Status = UpdatePossibleResource(Table, PossibleIrqNumBuf, PossibleIrqNumBufSize, &IsShortFormPkgLength);\r
DEBUG ((\r
DEBUG_INFO,\r
"UpdatePossibleResource status - %x. TPM2 service may not ready in OS.\n",\r
mTcgNvs = AssignOpRegion (Table, SIGNATURE_32 ('T', 'N', 'V', 'S'), (UINT16) sizeof (TCG_NVS));\r
ASSERT (mTcgNvs != NULL);\r
mTcgNvs->TpmIrqNum = PcdGet32(PcdTpm2CurrentIrqNum);\r
- mTcgNvs->IsShortFormPkgLength = FALSE;\r
+ mTcgNvs->IsShortFormPkgLength = IsShortFormPkgLength;\r
\r
//\r
- // Publish the TPM ACPI table. Table is re-checksumed.\r
+ // Publish the TPM ACPI table. Table is re-checksummed.\r
//\r
Status = gBS->LocateProtocol (&gEfiAcpiTableProtocolGuid, NULL, (VOID **) &AcpiTable);\r
ASSERT_EFI_ERROR (Status);\r
UINTN TableKey;\r
UINT64 OemTableId;\r
EFI_TPM2_ACPI_CONTROL_AREA *ControlArea;\r
- PTP_INTERFACE_TYPE InterfaceType;\r
+ TPM2_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
// PlatformClass is only valid for version 4 and above\r
- // BIT0~15: PlatformClass \r
+ // BIT0~15: PlatformClass\r
// BIT16~31: Reserved\r
//\r
if (mTpm2AcpiTemplate.Header.Revision >= EFI_TPM2_ACPI_TABLE_REVISION_4) {\r
DEBUG((DEBUG_INFO, "Tpm2 ACPI table PlatformClass is %d\n", (mTpm2AcpiTemplate.Flags & 0x0000FFFF)));\r
}\r
\r
+ mTpm2AcpiTemplate.Laml = PcdGet32(PcdTpm2AcpiTableLaml);\r
+ mTpm2AcpiTemplate.Lasa = PcdGet64(PcdTpm2AcpiTableLasa);\r
+ if ((mTpm2AcpiTemplate.Header.Revision < EFI_TPM2_ACPI_TABLE_REVISION_4) ||\r
+ (mTpm2AcpiTemplate.Laml == 0) || (mTpm2AcpiTemplate.Lasa == 0)) {\r
+ //\r
+ // If version is smaller than 4 or Laml/Lasa is not valid, rollback to original Length.\r
+ //\r
+ mTpm2AcpiTemplate.Header.Length = sizeof(EFI_TPM2_ACPI_TABLE);\r
+ }\r
+\r
//\r
// Measure to PCR[0] with event EV_POST_CODE ACPI DATA\r
//\r
EV_POSTCODE_INFO_ACPI_DATA,\r
ACPI_DATA_LEN,\r
&mTpm2AcpiTemplate,\r
- sizeof(mTpm2AcpiTemplate)\r
+ mTpm2AcpiTemplate.Header.Length\r
);\r
\r
- InterfaceType = GetPtpInterface ((VOID *) (UINTN) PcdGet64 (PcdTpmBaseAddress));\r
+ InterfaceType = PcdGet8(PcdActiveTpmInterfaceType);\r
switch (InterfaceType) {\r
- case PtpInterfaceCrb:\r
+ case Tpm2PtpInterfaceCrb:\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->Command = PcdGet64 (PcdTpmBaseAddress) + 0x80;\r
ControlArea->Response = PcdGet64 (PcdTpmBaseAddress) + 0x80;\r
break;\r
- case PtpInterfaceFifo:\r
- case PtpInterfaceTis:\r
+ case Tpm2PtpInterfaceFifo:\r
+ case Tpm2PtpInterfaceTis:\r
break;\r
default:\r
DEBUG((EFI_D_ERROR, "TPM2 InterfaceType get error! %d\n", InterfaceType));\r
Status = AcpiTable->InstallAcpiTable (\r
AcpiTable,\r
&mTpm2AcpiTemplate,\r
- sizeof(mTpm2AcpiTemplate),\r
+ mTpm2AcpiTemplate.Header.Length,\r
&TableKey\r
);\r
ASSERT_EFI_ERROR (Status);\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] ImageHandle The firmware allocated handle for the EFI image.\r
@param[in] SystemTable A pointer to the EFI System Table.\r
- \r
+\r
@retval EFI_SUCCESS The entry point is executed successfully.\r
@retval Others Some error occurs when executing this entry point.\r
\r
return Status;\r
}\r
mTcgNvs->MemoryClear.SoftwareSmi = (UINT8) SwContext.SwSmiInputValue;\r
- \r
+\r
//\r
// Locate SmmVariableProtocol.\r
//\r