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 Initialize and publish TPM items in ACPI table.
256 @retval EFI_SUCCESS The TCG ACPI table is published successfully.
257 @retval Others The TCG ACPI table is not published.
266 EFI_ACPI_TABLE_PROTOCOL
*AcpiTable
;
268 EFI_ACPI_DESCRIPTION_HEADER
*Table
;
271 Status
= GetSectionFromFv (
278 ASSERT_EFI_ERROR (Status
);
282 // Measure to PCR[0] with event EV_POST_CODE ACPI DATA
284 TpmMeasureAndLogData(
287 EV_POSTCODE_INFO_ACPI_DATA
,
294 ASSERT (Table
->OemTableId
== SIGNATURE_64 ('T', 'p', 'm', '2', 'T', 'a', 'b', 'l'));
295 CopyMem (Table
->OemId
, PcdGetPtr (PcdAcpiDefaultOemId
), sizeof (Table
->OemId
) );
296 mTcgNvs
= AssignOpRegion (Table
, SIGNATURE_32 ('T', 'N', 'V', 'S'), (UINT16
) sizeof (TCG_NVS
));
297 ASSERT (mTcgNvs
!= NULL
);
300 // Publish the TPM ACPI table
302 Status
= gBS
->LocateProtocol (&gEfiAcpiTableProtocolGuid
, NULL
, (VOID
**) &AcpiTable
);
303 ASSERT_EFI_ERROR (Status
);
306 Status
= AcpiTable
->InstallAcpiTable (
312 ASSERT_EFI_ERROR (Status
);
318 Publish TPM2 ACPI table
320 @retval EFI_SUCCESS The TPM2 ACPI table is published successfully.
321 @retval Others The TPM2 ACPI table is not published.
330 EFI_ACPI_TABLE_PROTOCOL
*AcpiTable
;
333 EFI_TPM2_ACPI_CONTROL_AREA
*ControlArea
;
334 PTP_INTERFACE_TYPE InterfaceType
;
337 // Measure to PCR[0] with event EV_POST_CODE ACPI DATA
339 TpmMeasureAndLogData(
342 EV_POSTCODE_INFO_ACPI_DATA
,
345 sizeof(mTpm2AcpiTemplate
)
348 InterfaceType
= GetPtpInterface ((VOID
*) (UINTN
) PcdGet64 (PcdTpmBaseAddress
));
349 switch (InterfaceType
) {
350 case PtpInterfaceCrb
:
351 mTpm2AcpiTemplate
.StartMethod
= EFI_TPM2_ACPI_TABLE_START_METHOD_COMMAND_RESPONSE_BUFFER_INTERFACE
;
352 mTpm2AcpiTemplate
.AddressOfControlArea
= PcdGet64 (PcdTpmBaseAddress
) + 0x40;
353 ControlArea
= (EFI_TPM2_ACPI_CONTROL_AREA
*)(UINTN
)mTpm2AcpiTemplate
.AddressOfControlArea
;
354 ControlArea
->CommandSize
= 0xF80;
355 ControlArea
->ResponseSize
= 0xF80;
356 ControlArea
->Command
= PcdGet64 (PcdTpmBaseAddress
) + 0x80;
357 ControlArea
->Response
= PcdGet64 (PcdTpmBaseAddress
) + 0x80;
359 case PtpInterfaceFifo
:
360 case PtpInterfaceTis
:
366 CopyMem (mTpm2AcpiTemplate
.Header
.OemId
, PcdGetPtr (PcdAcpiDefaultOemId
), sizeof (mTpm2AcpiTemplate
.Header
.OemId
));
367 OemTableId
= PcdGet64 (PcdAcpiDefaultOemTableId
);
368 CopyMem (&mTpm2AcpiTemplate
.Header
.OemTableId
, &OemTableId
, sizeof (UINT64
));
369 mTpm2AcpiTemplate
.Header
.OemRevision
= PcdGet32 (PcdAcpiDefaultOemRevision
);
370 mTpm2AcpiTemplate
.Header
.CreatorId
= PcdGet32 (PcdAcpiDefaultCreatorId
);
371 mTpm2AcpiTemplate
.Header
.CreatorRevision
= PcdGet32 (PcdAcpiDefaultCreatorRevision
);
374 // Construct ACPI table
376 Status
= gBS
->LocateProtocol (&gEfiAcpiTableProtocolGuid
, NULL
, (VOID
**) &AcpiTable
);
377 ASSERT_EFI_ERROR (Status
);
379 Status
= AcpiTable
->InstallAcpiTable (
382 sizeof(mTpm2AcpiTemplate
),
385 ASSERT_EFI_ERROR (Status
);
391 The driver's entry point.
393 It install callbacks for TPM physical presence and MemoryClear, and locate
394 SMM variable to be used in the callback function.
396 @param[in] ImageHandle The firmware allocated handle for the EFI image.
397 @param[in] SystemTable A pointer to the EFI System Table.
399 @retval EFI_SUCCESS The entry point is executed successfully.
400 @retval Others Some error occurs when executing this entry point.
406 IN EFI_HANDLE ImageHandle
,
407 IN EFI_SYSTEM_TABLE
*SystemTable
411 EFI_SMM_SW_DISPATCH2_PROTOCOL
*SwDispatch
;
412 EFI_SMM_SW_REGISTER_CONTEXT SwContext
;
415 if (!CompareGuid (PcdGetPtr(PcdTpmInstanceGuid
), &gEfiTpmDeviceInstanceTpm20DtpmGuid
)){
416 DEBUG ((EFI_D_ERROR
, "No TPM2 DTPM instance required!\n"));
417 return EFI_UNSUPPORTED
;
420 Status
= PublishAcpiTable ();
421 ASSERT_EFI_ERROR (Status
);
424 // Get the Sw dispatch protocol and register SMI callback functions.
426 Status
= gSmst
->SmmLocateProtocol (&gEfiSmmSwDispatch2ProtocolGuid
, NULL
, (VOID
**)&SwDispatch
);
427 ASSERT_EFI_ERROR (Status
);
428 SwContext
.SwSmiInputValue
= (UINTN
) -1;
429 Status
= SwDispatch
->Register (SwDispatch
, PhysicalPresenceCallback
, &SwContext
, &SwHandle
);
430 ASSERT_EFI_ERROR (Status
);
431 if (EFI_ERROR (Status
)) {
434 mTcgNvs
->PhysicalPresence
.SoftwareSmi
= (UINT8
) SwContext
.SwSmiInputValue
;
436 SwContext
.SwSmiInputValue
= (UINTN
) -1;
437 Status
= SwDispatch
->Register (SwDispatch
, MemoryClearCallback
, &SwContext
, &SwHandle
);
438 ASSERT_EFI_ERROR (Status
);
439 if (EFI_ERROR (Status
)) {
442 mTcgNvs
->MemoryClear
.SoftwareSmi
= (UINT8
) SwContext
.SwSmiInputValue
;
445 // Locate SmmVariableProtocol.
447 Status
= gSmst
->SmmLocateProtocol (&gEfiSmmVariableProtocolGuid
, NULL
, (VOID
**)&mSmmVariable
);
448 ASSERT_EFI_ERROR (Status
);
451 // Set TPM2 ACPI table
453 Status
= PublishTpm2 ();
454 ASSERT_EFI_ERROR (Status
);