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, 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.
25 EFI_TPM2_ACPI_TABLE mTpm2AcpiTemplate
= {
27 EFI_ACPI_5_0_TRUSTED_COMPUTING_PLATFORM_2_TABLE_SIGNATURE
,
28 sizeof (mTpm2AcpiTemplate
),
29 EFI_TPM2_ACPI_TABLE_REVISION
,
31 // Compiler initializes the remaining bytes to 0
32 // These fields should be filled in in production
37 EFI_TPM2_ACPI_TABLE_START_METHOD_TIS
, // StartMethod
40 EFI_SMM_VARIABLE_PROTOCOL
*mSmmVariable
;
44 Software SMI callback for TPM physical presence which is called from ACPI method.
46 Caution: This function may receive untrusted input.
47 Variable and ACPINvs are external input, so this function will validate
48 its data structure to be valid value.
50 @param[in] DispatchHandle The unique handle assigned to this handler by SmiHandlerRegister().
51 @param[in] Context Points to an optional handler context which was specified when the
52 handler was registered.
53 @param[in, out] CommBuffer A pointer to a collection of data in memory that will
54 be conveyed from a non-SMM environment into an SMM environment.
55 @param[in, out] CommBufferSize The size of the CommBuffer.
57 @retval EFI_SUCCESS The interrupt was handled successfully.
62 PhysicalPresenceCallback (
63 IN EFI_HANDLE DispatchHandle
,
64 IN CONST VOID
*Context
,
65 IN OUT VOID
*CommBuffer
,
66 IN OUT UINTN
*CommBufferSize
69 UINT32 MostRecentRequest
;
72 if (mTcgNvs
->PhysicalPresence
.Parameter
== TCG_ACPI_FUNCTION_RETURN_REQUEST_RESPONSE_TO_OS
) {
73 mTcgNvs
->PhysicalPresence
.ReturnCode
= Tcg2PhysicalPresenceLibReturnOperationResponseToOsFunction (
77 mTcgNvs
->PhysicalPresence
.LastRequest
= MostRecentRequest
;
78 mTcgNvs
->PhysicalPresence
.Response
= Response
;
80 } else if ((mTcgNvs
->PhysicalPresence
.Parameter
== TCG_ACPI_FUNCTION_SUBMIT_REQUEST_TO_BIOS
)
81 || (mTcgNvs
->PhysicalPresence
.Parameter
== TCG_ACPI_FUNCTION_SUBMIT_REQUEST_TO_BIOS_2
)) {
82 mTcgNvs
->PhysicalPresence
.ReturnCode
= Tcg2PhysicalPresenceLibSubmitRequestToPreOSFunction (
83 mTcgNvs
->PhysicalPresence
.Request
,
84 mTcgNvs
->PhysicalPresence
.RequestParameter
86 } else if (mTcgNvs
->PhysicalPresence
.Parameter
== TCG_ACPI_FUNCTION_GET_USER_CONFIRMATION_STATUS_FOR_REQUEST
) {
87 mTcgNvs
->PhysicalPresence
.ReturnCode
= Tcg2PhysicalPresenceLibGetUserConfirmationStatusFunction (mTcgNvs
->PhysicalPresence
.Request
);
95 Software SMI callback for MemoryClear which is called from ACPI method.
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.
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.
108 @retval EFI_SUCCESS The interrupt was handled successfully.
113 MemoryClearCallback (
114 IN EFI_HANDLE DispatchHandle
,
115 IN CONST VOID
*Context
,
116 IN OUT VOID
*CommBuffer
,
117 IN OUT UINTN
*CommBufferSize
124 mTcgNvs
->MemoryClear
.ReturnCode
= MOR_REQUEST_SUCCESS
;
125 if (mTcgNvs
->MemoryClear
.Parameter
== ACPI_FUNCTION_DSM_MEMORY_CLEAR_INTERFACE
) {
126 MorControl
= (UINT8
) mTcgNvs
->MemoryClear
.Request
;
127 } else if (mTcgNvs
->MemoryClear
.Parameter
== ACPI_FUNCTION_PTS_CLEAR_MOR_BIT
) {
128 DataSize
= sizeof (UINT8
);
129 Status
= mSmmVariable
->SmmGetVariable (
130 MEMORY_OVERWRITE_REQUEST_VARIABLE_NAME
,
131 &gEfiMemoryOverwriteControlDataGuid
,
136 if (EFI_ERROR (Status
)) {
137 mTcgNvs
->MemoryClear
.ReturnCode
= MOR_REQUEST_GENERAL_FAILURE
;
138 DEBUG ((EFI_D_ERROR
, "[TPM] Get MOR variable failure! Status = %r\n", Status
));
142 if (MOR_CLEAR_MEMORY_VALUE (MorControl
) == 0x0) {
145 MorControl
&= ~MOR_CLEAR_MEMORY_BIT_MASK
;
148 DataSize
= sizeof (UINT8
);
149 Status
= mSmmVariable
->SmmSetVariable (
150 MEMORY_OVERWRITE_REQUEST_VARIABLE_NAME
,
151 &gEfiMemoryOverwriteControlDataGuid
,
152 EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_RUNTIME_ACCESS
,
156 if (EFI_ERROR (Status
)) {
157 mTcgNvs
->MemoryClear
.ReturnCode
= MOR_REQUEST_GENERAL_FAILURE
;
158 DEBUG ((EFI_D_ERROR
, "[TPM] Set MOR variable failure! Status = %r\n", Status
));
165 Find the operation region in TCG ACPI table by given Name and Size,
166 and initialize it if the region is found.
168 @param[in, out] Table The TPM item in ACPI table.
169 @param[in] Name The name string to find in TPM table.
170 @param[in] Size The size of the region to find.
172 @return The allocated address for the found region.
177 EFI_ACPI_DESCRIPTION_HEADER
*Table
,
183 AML_OP_REGION_32_8
*OpRegion
;
184 EFI_PHYSICAL_ADDRESS MemoryAddress
;
186 MemoryAddress
= SIZE_4GB
- 1;
189 // Patch some pointers for the ASL code before loading the SSDT.
191 for (OpRegion
= (AML_OP_REGION_32_8
*) (Table
+ 1);
192 OpRegion
<= (AML_OP_REGION_32_8
*) ((UINT8
*) Table
+ Table
->Length
);
193 OpRegion
= (AML_OP_REGION_32_8
*) ((UINT8
*) OpRegion
+ 1)) {
194 if ((OpRegion
->OpRegionOp
== AML_EXT_REGION_OP
) &&
195 (OpRegion
->NameString
== Name
) &&
196 (OpRegion
->DWordPrefix
== AML_DWORD_PREFIX
) &&
197 (OpRegion
->BytePrefix
== AML_BYTE_PREFIX
)) {
199 Status
= gBS
->AllocatePages(AllocateMaxAddress
, EfiACPIMemoryNVS
, EFI_SIZE_TO_PAGES (Size
), &MemoryAddress
);
200 ASSERT_EFI_ERROR (Status
);
201 ZeroMem ((VOID
*)(UINTN
)MemoryAddress
, Size
);
202 OpRegion
->RegionOffset
= (UINT32
) (UINTN
) MemoryAddress
;
203 OpRegion
->RegionLen
= (UINT8
) Size
;
208 return (VOID
*) (UINTN
) MemoryAddress
;
212 Initialize and publish TPM items in ACPI table.
214 @retval EFI_SUCCESS The TCG ACPI table is published successfully.
215 @retval Others The TCG ACPI table is not published.
224 EFI_ACPI_TABLE_PROTOCOL
*AcpiTable
;
226 EFI_ACPI_DESCRIPTION_HEADER
*Table
;
229 Status
= GetSectionFromFv (
236 ASSERT_EFI_ERROR (Status
);
240 // Measure to PCR[0] with event EV_POST_CODE ACPI DATA
242 TpmMeasureAndLogData(
245 EV_POSTCODE_INFO_ACPI_DATA
,
252 ASSERT (Table
->OemTableId
== SIGNATURE_64 ('T', 'p', 'm', '2', 'T', 'a', 'b', 'l'));
253 CopyMem (Table
->OemId
, PcdGetPtr (PcdAcpiDefaultOemId
), sizeof (Table
->OemId
) );
254 mTcgNvs
= AssignOpRegion (Table
, SIGNATURE_32 ('T', 'N', 'V', 'S'), (UINT16
) sizeof (TCG_NVS
));
255 ASSERT (mTcgNvs
!= NULL
);
258 // Publish the TPM ACPI table
260 Status
= gBS
->LocateProtocol (&gEfiAcpiTableProtocolGuid
, NULL
, (VOID
**) &AcpiTable
);
261 ASSERT_EFI_ERROR (Status
);
264 Status
= AcpiTable
->InstallAcpiTable (
270 ASSERT_EFI_ERROR (Status
);
276 Publish TPM2 ACPI table
278 @retval EFI_SUCCESS The TPM2 ACPI table is published successfully.
279 @retval Others The TPM2 ACPI table is not published.
288 EFI_ACPI_TABLE_PROTOCOL
*AcpiTable
;
293 // Measure to PCR[0] with event EV_POST_CODE ACPI DATA
295 TpmMeasureAndLogData(
298 EV_POSTCODE_INFO_ACPI_DATA
,
301 sizeof(mTpm2AcpiTemplate
)
304 CopyMem (mTpm2AcpiTemplate
.Header
.OemId
, PcdGetPtr (PcdAcpiDefaultOemId
), sizeof (mTpm2AcpiTemplate
.Header
.OemId
));
305 OemTableId
= PcdGet64 (PcdAcpiDefaultOemTableId
);
306 CopyMem (&mTpm2AcpiTemplate
.Header
.OemTableId
, &OemTableId
, sizeof (UINT64
));
307 mTpm2AcpiTemplate
.Header
.OemRevision
= PcdGet32 (PcdAcpiDefaultOemRevision
);
308 mTpm2AcpiTemplate
.Header
.CreatorId
= PcdGet32 (PcdAcpiDefaultCreatorId
);
309 mTpm2AcpiTemplate
.Header
.CreatorRevision
= PcdGet32 (PcdAcpiDefaultCreatorRevision
);
312 // Construct ACPI table
314 Status
= gBS
->LocateProtocol (&gEfiAcpiTableProtocolGuid
, NULL
, (VOID
**) &AcpiTable
);
315 ASSERT_EFI_ERROR (Status
);
317 Status
= AcpiTable
->InstallAcpiTable (
320 sizeof(mTpm2AcpiTemplate
),
323 ASSERT_EFI_ERROR (Status
);
329 The driver's entry point.
331 It install callbacks for TPM physical presence and MemoryClear, and locate
332 SMM variable to be used in the callback function.
334 @param[in] ImageHandle The firmware allocated handle for the EFI image.
335 @param[in] SystemTable A pointer to the EFI System Table.
337 @retval EFI_SUCCESS The entry point is executed successfully.
338 @retval Others Some error occurs when executing this entry point.
344 IN EFI_HANDLE ImageHandle
,
345 IN EFI_SYSTEM_TABLE
*SystemTable
349 EFI_SMM_SW_DISPATCH2_PROTOCOL
*SwDispatch
;
350 EFI_SMM_SW_REGISTER_CONTEXT SwContext
;
353 if (!CompareGuid (PcdGetPtr(PcdTpmInstanceGuid
), &gEfiTpmDeviceInstanceTpm20DtpmGuid
)){
354 DEBUG ((EFI_D_ERROR
, "No TPM2 DTPM instance required!\n"));
355 return EFI_UNSUPPORTED
;
358 Status
= PublishAcpiTable ();
359 ASSERT_EFI_ERROR (Status
);
362 // Get the Sw dispatch protocol and register SMI callback functions.
364 Status
= gSmst
->SmmLocateProtocol (&gEfiSmmSwDispatch2ProtocolGuid
, NULL
, (VOID
**)&SwDispatch
);
365 ASSERT_EFI_ERROR (Status
);
366 SwContext
.SwSmiInputValue
= (UINTN
) -1;
367 Status
= SwDispatch
->Register (SwDispatch
, PhysicalPresenceCallback
, &SwContext
, &SwHandle
);
368 ASSERT_EFI_ERROR (Status
);
369 if (EFI_ERROR (Status
)) {
372 mTcgNvs
->PhysicalPresence
.SoftwareSmi
= (UINT8
) SwContext
.SwSmiInputValue
;
374 SwContext
.SwSmiInputValue
= (UINTN
) -1;
375 Status
= SwDispatch
->Register (SwDispatch
, MemoryClearCallback
, &SwContext
, &SwHandle
);
376 ASSERT_EFI_ERROR (Status
);
377 if (EFI_ERROR (Status
)) {
380 mTcgNvs
->MemoryClear
.SoftwareSmi
= (UINT8
) SwContext
.SwSmiInputValue
;
383 // Locate SmmVariableProtocol.
385 Status
= gSmst
->SmmLocateProtocol (&gEfiSmmVariableProtocolGuid
, NULL
, (VOID
**)&mSmmVariable
);
386 ASSERT_EFI_ERROR (Status
);
389 // Set TPM2 ACPI table
391 Status
= PublishTpm2 ();
392 ASSERT_EFI_ERROR (Status
);