2 It updates TPM2 items in ACPI table and registers SMI2 callback
3 functions for Tcg2 physical presence, ClearMemory, and sample
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.
10 PhysicalPresenceCallback() and MemoryClearCallback() will receive untrusted input and do some check.
12 Copyright (c) 2015 - 2016, 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
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.
33 Return PTP interface type.
35 @param[in] Register Pointer to PTP register.
37 @return PTP interface type.
44 PTP_CRB_INTERFACE_IDENTIFIER InterfaceId
;
45 PTP_FIFO_INTERFACE_CAPABILITY InterfaceCapability
;
50 InterfaceId
.Uint32
= MmioRead32 ((UINTN
)&((PTP_CRB_REGISTERS
*)Register
)->InterfaceId
);
51 InterfaceCapability
.Uint32
= MmioRead32 ((UINTN
)&((PTP_FIFO_REGISTERS
*)Register
)->InterfaceCapability
);
53 if ((InterfaceId
.Bits
.InterfaceType
== PTP_INTERFACE_IDENTIFIER_INTERFACE_TYPE_CRB
) &&
54 (InterfaceId
.Bits
.InterfaceVersion
== PTP_INTERFACE_IDENTIFIER_INTERFACE_VERSION_CRB
) &&
55 (InterfaceId
.Bits
.CapCRB
!= 0)) {
56 return PtpInterfaceCrb
;
58 if ((InterfaceId
.Bits
.InterfaceType
== PTP_INTERFACE_IDENTIFIER_INTERFACE_TYPE_FIFO
) &&
59 (InterfaceId
.Bits
.InterfaceVersion
== PTP_INTERFACE_IDENTIFIER_INTERFACE_VERSION_FIFO
) &&
60 (InterfaceId
.Bits
.CapFIFO
!= 0) &&
61 (InterfaceCapability
.Bits
.InterfaceVersion
== INTERFACE_CAPABILITY_INTERFACE_VERSION_PTP
)) {
62 return PtpInterfaceFifo
;
64 return PtpInterfaceTis
;
67 EFI_TPM2_ACPI_TABLE mTpm2AcpiTemplate
= {
69 EFI_ACPI_5_0_TRUSTED_COMPUTING_PLATFORM_2_TABLE_SIGNATURE
,
70 sizeof (mTpm2AcpiTemplate
),
71 EFI_TPM2_ACPI_TABLE_REVISION
,
73 // Compiler initializes the remaining bytes to 0
74 // These fields should be filled in in production
79 EFI_TPM2_ACPI_TABLE_START_METHOD_TIS
, // StartMethod
82 EFI_SMM_VARIABLE_PROTOCOL
*mSmmVariable
;
86 Software SMI callback for TPM physical presence which is called from ACPI method.
88 Caution: This function may receive untrusted input.
89 Variable and ACPINvs are external input, so this function will validate
90 its data structure to be valid value.
92 @param[in] DispatchHandle The unique handle assigned to this handler by SmiHandlerRegister().
93 @param[in] Context Points to an optional handler context which was specified when the
94 handler was registered.
95 @param[in, out] CommBuffer A pointer to a collection of data in memory that will
96 be conveyed from a non-SMM environment into an SMM environment.
97 @param[in, out] CommBufferSize The size of the CommBuffer.
99 @retval EFI_SUCCESS The interrupt was handled successfully.
104 PhysicalPresenceCallback (
105 IN EFI_HANDLE DispatchHandle
,
106 IN CONST VOID
*Context
,
107 IN OUT VOID
*CommBuffer
,
108 IN OUT UINTN
*CommBufferSize
111 UINT32 MostRecentRequest
;
114 if (mTcgNvs
->PhysicalPresence
.Parameter
== TCG_ACPI_FUNCTION_RETURN_REQUEST_RESPONSE_TO_OS
) {
115 mTcgNvs
->PhysicalPresence
.ReturnCode
= Tcg2PhysicalPresenceLibReturnOperationResponseToOsFunction (
119 mTcgNvs
->PhysicalPresence
.LastRequest
= MostRecentRequest
;
120 mTcgNvs
->PhysicalPresence
.Response
= Response
;
122 } else if ((mTcgNvs
->PhysicalPresence
.Parameter
== TCG_ACPI_FUNCTION_SUBMIT_REQUEST_TO_BIOS
)
123 || (mTcgNvs
->PhysicalPresence
.Parameter
== TCG_ACPI_FUNCTION_SUBMIT_REQUEST_TO_BIOS_2
)) {
124 mTcgNvs
->PhysicalPresence
.ReturnCode
= Tcg2PhysicalPresenceLibSubmitRequestToPreOSFunction (
125 mTcgNvs
->PhysicalPresence
.Request
,
126 mTcgNvs
->PhysicalPresence
.RequestParameter
128 } else if (mTcgNvs
->PhysicalPresence
.Parameter
== TCG_ACPI_FUNCTION_GET_USER_CONFIRMATION_STATUS_FOR_REQUEST
) {
129 mTcgNvs
->PhysicalPresence
.ReturnCode
= Tcg2PhysicalPresenceLibGetUserConfirmationStatusFunction (mTcgNvs
->PhysicalPresence
.Request
);
137 Software SMI callback for MemoryClear which is called from ACPI method.
139 Caution: This function may receive untrusted input.
140 Variable and ACPINvs are external input, so this function will validate
141 its data structure to be valid value.
143 @param[in] DispatchHandle The unique handle assigned to this handler by SmiHandlerRegister().
144 @param[in] Context Points to an optional handler context which was specified when the
145 handler was registered.
146 @param[in, out] CommBuffer A pointer to a collection of data in memory that will
147 be conveyed from a non-SMM environment into an SMM environment.
148 @param[in, out] CommBufferSize The size of the CommBuffer.
150 @retval EFI_SUCCESS The interrupt was handled successfully.
155 MemoryClearCallback (
156 IN EFI_HANDLE DispatchHandle
,
157 IN CONST VOID
*Context
,
158 IN OUT VOID
*CommBuffer
,
159 IN OUT UINTN
*CommBufferSize
166 mTcgNvs
->MemoryClear
.ReturnCode
= MOR_REQUEST_SUCCESS
;
167 if (mTcgNvs
->MemoryClear
.Parameter
== ACPI_FUNCTION_DSM_MEMORY_CLEAR_INTERFACE
) {
168 MorControl
= (UINT8
) mTcgNvs
->MemoryClear
.Request
;
169 } else if (mTcgNvs
->MemoryClear
.Parameter
== ACPI_FUNCTION_PTS_CLEAR_MOR_BIT
) {
170 DataSize
= sizeof (UINT8
);
171 Status
= mSmmVariable
->SmmGetVariable (
172 MEMORY_OVERWRITE_REQUEST_VARIABLE_NAME
,
173 &gEfiMemoryOverwriteControlDataGuid
,
178 if (EFI_ERROR (Status
)) {
179 mTcgNvs
->MemoryClear
.ReturnCode
= MOR_REQUEST_GENERAL_FAILURE
;
180 DEBUG ((EFI_D_ERROR
, "[TPM] Get MOR variable failure! Status = %r\n", Status
));
184 if (MOR_CLEAR_MEMORY_VALUE (MorControl
) == 0x0) {
187 MorControl
&= ~MOR_CLEAR_MEMORY_BIT_MASK
;
190 DataSize
= sizeof (UINT8
);
191 Status
= mSmmVariable
->SmmSetVariable (
192 MEMORY_OVERWRITE_REQUEST_VARIABLE_NAME
,
193 &gEfiMemoryOverwriteControlDataGuid
,
194 EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_RUNTIME_ACCESS
,
198 if (EFI_ERROR (Status
)) {
199 mTcgNvs
->MemoryClear
.ReturnCode
= MOR_REQUEST_GENERAL_FAILURE
;
200 DEBUG ((EFI_D_ERROR
, "[TPM] Set MOR variable failure! Status = %r\n", Status
));
207 Find the operation region in TCG ACPI table by given Name and Size,
208 and initialize it if the region is found.
210 @param[in, out] Table The TPM item in ACPI table.
211 @param[in] Name The name string to find in TPM table.
212 @param[in] Size The size of the region to find.
214 @return The allocated address for the found region.
219 EFI_ACPI_DESCRIPTION_HEADER
*Table
,
225 AML_OP_REGION_32_8
*OpRegion
;
226 EFI_PHYSICAL_ADDRESS MemoryAddress
;
228 MemoryAddress
= SIZE_4GB
- 1;
231 // Patch some pointers for the ASL code before loading the SSDT.
233 for (OpRegion
= (AML_OP_REGION_32_8
*) (Table
+ 1);
234 OpRegion
<= (AML_OP_REGION_32_8
*) ((UINT8
*) Table
+ Table
->Length
);
235 OpRegion
= (AML_OP_REGION_32_8
*) ((UINT8
*) OpRegion
+ 1)) {
236 if ((OpRegion
->OpRegionOp
== AML_EXT_REGION_OP
) &&
237 (OpRegion
->NameString
== Name
) &&
238 (OpRegion
->DWordPrefix
== AML_DWORD_PREFIX
) &&
239 (OpRegion
->BytePrefix
== AML_BYTE_PREFIX
)) {
241 Status
= gBS
->AllocatePages(AllocateMaxAddress
, EfiACPIMemoryNVS
, EFI_SIZE_TO_PAGES (Size
), &MemoryAddress
);
242 ASSERT_EFI_ERROR (Status
);
243 ZeroMem ((VOID
*)(UINTN
)MemoryAddress
, Size
);
244 OpRegion
->RegionOffset
= (UINT32
) (UINTN
) MemoryAddress
;
245 OpRegion
->RegionLen
= (UINT8
) Size
;
250 return (VOID
*) (UINTN
) MemoryAddress
;
254 Patch version string of Physical Presence interface supported by platform. The initial string tag in TPM
257 @param[in, out] Table The TPM item in ACPI table.
258 @param[in] PPVer Version string of Physical Presence interface supported by platform.
260 @return The allocated address for the found region.
265 EFI_ACPI_DESCRIPTION_HEADER
*Table
,
273 // Patch some pointers for the ASL code before loading the SSDT.
275 for (DataPtr
= (UINT8
*)(Table
+ 1);
276 DataPtr
<= (UINT8
*) ((UINT8
*) Table
+ Table
->Length
- PHYSICAL_PRESENCE_VERSION_SIZE
);
278 if (AsciiStrCmp(DataPtr
, PHYSICAL_PRESENCE_VERSION_TAG
) == 0) {
279 Status
= AsciiStrCpyS(DataPtr
, PHYSICAL_PRESENCE_VERSION_SIZE
, PPVer
);
280 DEBUG((EFI_D_INFO
, "TPM2 Physical Presence Interface Version update status 0x%x\n", Status
));
285 return EFI_NOT_FOUND
;
289 Initialize and publish TPM items in ACPI table.
291 @retval EFI_SUCCESS The TCG ACPI table is published successfully.
292 @retval Others The TCG ACPI table is not published.
301 EFI_ACPI_TABLE_PROTOCOL
*AcpiTable
;
303 EFI_ACPI_DESCRIPTION_HEADER
*Table
;
306 Status
= GetSectionFromFv (
313 ASSERT_EFI_ERROR (Status
);
316 // Update Table version before measuring it to PCR
318 Status
= UpdatePPVersion(Table
, (CHAR8
*)PcdGetPtr(PcdTcgPhysicalPresenceInterfaceVer
));
319 ASSERT_EFI_ERROR (Status
);
322 // Measure to PCR[0] with event EV_POST_CODE ACPI DATA
324 TpmMeasureAndLogData(
327 EV_POSTCODE_INFO_ACPI_DATA
,
334 ASSERT (Table
->OemTableId
== SIGNATURE_64 ('T', 'p', 'm', '2', 'T', 'a', 'b', 'l'));
335 CopyMem (Table
->OemId
, PcdGetPtr (PcdAcpiDefaultOemId
), sizeof (Table
->OemId
) );
336 mTcgNvs
= AssignOpRegion (Table
, SIGNATURE_32 ('T', 'N', 'V', 'S'), (UINT16
) sizeof (TCG_NVS
));
337 ASSERT (mTcgNvs
!= NULL
);
340 // Publish the TPM ACPI table. Table is re-checksumed.
342 Status
= gBS
->LocateProtocol (&gEfiAcpiTableProtocolGuid
, NULL
, (VOID
**) &AcpiTable
);
343 ASSERT_EFI_ERROR (Status
);
346 Status
= AcpiTable
->InstallAcpiTable (
352 ASSERT_EFI_ERROR (Status
);
358 Publish TPM2 ACPI table
360 @retval EFI_SUCCESS The TPM2 ACPI table is published successfully.
361 @retval Others The TPM2 ACPI table is not published.
370 EFI_ACPI_TABLE_PROTOCOL
*AcpiTable
;
373 EFI_TPM2_ACPI_CONTROL_AREA
*ControlArea
;
374 PTP_INTERFACE_TYPE InterfaceType
;
377 // Measure to PCR[0] with event EV_POST_CODE ACPI DATA
379 TpmMeasureAndLogData(
382 EV_POSTCODE_INFO_ACPI_DATA
,
385 sizeof(mTpm2AcpiTemplate
)
388 InterfaceType
= GetPtpInterface ((VOID
*) (UINTN
) PcdGet64 (PcdTpmBaseAddress
));
389 switch (InterfaceType
) {
390 case PtpInterfaceCrb
:
391 mTpm2AcpiTemplate
.StartMethod
= EFI_TPM2_ACPI_TABLE_START_METHOD_COMMAND_RESPONSE_BUFFER_INTERFACE
;
392 mTpm2AcpiTemplate
.AddressOfControlArea
= PcdGet64 (PcdTpmBaseAddress
) + 0x40;
393 ControlArea
= (EFI_TPM2_ACPI_CONTROL_AREA
*)(UINTN
)mTpm2AcpiTemplate
.AddressOfControlArea
;
394 ControlArea
->CommandSize
= 0xF80;
395 ControlArea
->ResponseSize
= 0xF80;
396 ControlArea
->Command
= PcdGet64 (PcdTpmBaseAddress
) + 0x80;
397 ControlArea
->Response
= PcdGet64 (PcdTpmBaseAddress
) + 0x80;
399 case PtpInterfaceFifo
:
400 case PtpInterfaceTis
:
406 CopyMem (mTpm2AcpiTemplate
.Header
.OemId
, PcdGetPtr (PcdAcpiDefaultOemId
), sizeof (mTpm2AcpiTemplate
.Header
.OemId
));
407 OemTableId
= PcdGet64 (PcdAcpiDefaultOemTableId
);
408 CopyMem (&mTpm2AcpiTemplate
.Header
.OemTableId
, &OemTableId
, sizeof (UINT64
));
409 mTpm2AcpiTemplate
.Header
.OemRevision
= PcdGet32 (PcdAcpiDefaultOemRevision
);
410 mTpm2AcpiTemplate
.Header
.CreatorId
= PcdGet32 (PcdAcpiDefaultCreatorId
);
411 mTpm2AcpiTemplate
.Header
.CreatorRevision
= PcdGet32 (PcdAcpiDefaultCreatorRevision
);
414 // Construct ACPI table
416 Status
= gBS
->LocateProtocol (&gEfiAcpiTableProtocolGuid
, NULL
, (VOID
**) &AcpiTable
);
417 ASSERT_EFI_ERROR (Status
);
419 Status
= AcpiTable
->InstallAcpiTable (
422 sizeof(mTpm2AcpiTemplate
),
425 ASSERT_EFI_ERROR (Status
);
431 The driver's entry point.
433 It install callbacks for TPM physical presence and MemoryClear, and locate
434 SMM variable to be used in the callback function.
436 @param[in] ImageHandle The firmware allocated handle for the EFI image.
437 @param[in] SystemTable A pointer to the EFI System Table.
439 @retval EFI_SUCCESS The entry point is executed successfully.
440 @retval Others Some error occurs when executing this entry point.
446 IN EFI_HANDLE ImageHandle
,
447 IN EFI_SYSTEM_TABLE
*SystemTable
451 EFI_SMM_SW_DISPATCH2_PROTOCOL
*SwDispatch
;
452 EFI_SMM_SW_REGISTER_CONTEXT SwContext
;
455 if (!CompareGuid (PcdGetPtr(PcdTpmInstanceGuid
), &gEfiTpmDeviceInstanceTpm20DtpmGuid
)){
456 DEBUG ((EFI_D_ERROR
, "No TPM2 DTPM instance required!\n"));
457 return EFI_UNSUPPORTED
;
460 Status
= PublishAcpiTable ();
461 ASSERT_EFI_ERROR (Status
);
464 // Get the Sw dispatch protocol and register SMI callback functions.
466 Status
= gSmst
->SmmLocateProtocol (&gEfiSmmSwDispatch2ProtocolGuid
, NULL
, (VOID
**)&SwDispatch
);
467 ASSERT_EFI_ERROR (Status
);
468 SwContext
.SwSmiInputValue
= (UINTN
) -1;
469 Status
= SwDispatch
->Register (SwDispatch
, PhysicalPresenceCallback
, &SwContext
, &SwHandle
);
470 ASSERT_EFI_ERROR (Status
);
471 if (EFI_ERROR (Status
)) {
474 mTcgNvs
->PhysicalPresence
.SoftwareSmi
= (UINT8
) SwContext
.SwSmiInputValue
;
476 SwContext
.SwSmiInputValue
= (UINTN
) -1;
477 Status
= SwDispatch
->Register (SwDispatch
, MemoryClearCallback
, &SwContext
, &SwHandle
);
478 ASSERT_EFI_ERROR (Status
);
479 if (EFI_ERROR (Status
)) {
482 mTcgNvs
->MemoryClear
.SoftwareSmi
= (UINT8
) SwContext
.SwSmiInputValue
;
485 // Locate SmmVariableProtocol.
487 Status
= gSmst
->SmmLocateProtocol (&gEfiSmmVariableProtocolGuid
, NULL
, (VOID
**)&mSmmVariable
);
488 ASSERT_EFI_ERROR (Status
);
491 // Set TPM2 ACPI table
493 Status
= PublishTpm2 ();
494 ASSERT_EFI_ERROR (Status
);