2 It updates TPM items in ACPI table and registers SMI callback
3 functions for physical presence and ClearMemory.
5 Caution: This module requires additional review when modified.
6 This driver will have external input - variable and ACPINvs data in SMM mode.
7 This external input must be validated carefully to avoid security issue.
9 PhysicalPresenceCallback() and MemoryClearCallback() will receive untrusted input and do some check.
11 Copyright (c) 2011 - 2012, Intel Corporation. All rights reserved.<BR>
12 This program and the accompanying materials
13 are licensed and made available under the terms and conditions of the BSD License
14 which accompanies this distribution. The full text of the license may be found at
15 http://opensource.org/licenses/bsd-license.php
17 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
18 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
24 EFI_SMM_VARIABLE_PROTOCOL
*mSmmVariable
;
28 Software SMI callback for TPM physical presence which is called from ACPI method.
30 Caution: This function may receive untrusted input.
31 Variable and ACPINvs are external input, so this function will validate
32 its data structure to be valid value.
34 @param[in] DispatchHandle The unique handle assigned to this handler by SmiHandlerRegister().
35 @param[in] Context Points to an optional handler context which was specified when the
36 handler was registered.
37 @param[in, out] CommBuffer A pointer to a collection of data in memory that will
38 be conveyed from a non-SMM environment into an SMM environment.
39 @param[in, out] CommBufferSize The size of the CommBuffer.
41 @retval EFI_SUCCESS The interrupt was handled successfully.
46 PhysicalPresenceCallback (
47 IN EFI_HANDLE DispatchHandle
,
48 IN CONST VOID
*Context
,
49 IN OUT VOID
*CommBuffer
,
50 IN OUT UINTN
*CommBufferSize
55 EFI_PHYSICAL_PRESENCE PpData
;
57 BOOLEAN RequestConfirmed
;
60 // Get the Physical Presence variable
62 DataSize
= sizeof (EFI_PHYSICAL_PRESENCE
);
63 Status
= mSmmVariable
->SmmGetVariable (
64 PHYSICAL_PRESENCE_VARIABLE
,
65 &gEfiPhysicalPresenceGuid
,
70 if (EFI_ERROR (Status
)) {
74 DEBUG ((EFI_D_INFO
, "[TPM] PP callback, Parameter = %x\n", mTcgNvs
->PhysicalPresence
.Parameter
));
75 if (mTcgNvs
->PhysicalPresence
.Parameter
== ACPI_FUNCTION_RETURN_REQUEST_RESPONSE_TO_OS
) {
76 mTcgNvs
->PhysicalPresence
.LastRequest
= PpData
.LastPPRequest
;
77 mTcgNvs
->PhysicalPresence
.Response
= PpData
.PPResponse
;
78 } else if ((mTcgNvs
->PhysicalPresence
.Parameter
== ACPI_FUNCTION_SUBMIT_REQUEST_TO_BIOS
)
79 || (mTcgNvs
->PhysicalPresence
.Parameter
== ACPI_FUNCTION_SUBMIT_REQUEST_TO_BIOS_2
)) {
80 if (mTcgNvs
->PhysicalPresence
.Request
== PHYSICAL_PRESENCE_SET_OPERATOR_AUTH
) {
82 // This command requires UI to prompt user for Auth data.
84 mTcgNvs
->PhysicalPresence
.ReturnCode
= PP_SUBMIT_REQUEST_NOT_IMPLEMENTED
;
88 if (PpData
.PPRequest
!= mTcgNvs
->PhysicalPresence
.Request
) {
89 PpData
.PPRequest
= (UINT8
) mTcgNvs
->PhysicalPresence
.Request
;
90 DataSize
= sizeof (EFI_PHYSICAL_PRESENCE
);
91 Status
= mSmmVariable
->SmmSetVariable (
92 PHYSICAL_PRESENCE_VARIABLE
,
93 &gEfiPhysicalPresenceGuid
,
94 EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_RUNTIME_ACCESS
,
100 if (EFI_ERROR (Status
)) {
101 mTcgNvs
->PhysicalPresence
.ReturnCode
= PP_SUBMIT_REQUEST_GENERAL_FAILURE
;
104 mTcgNvs
->PhysicalPresence
.ReturnCode
= PP_SUBMIT_REQUEST_SUCCESS
;
105 } else if (mTcgNvs
->PhysicalPresence
.Parameter
== ACPI_FUNCTION_GET_USER_CONFIRMATION_STATUS_FOR_REQUEST
) {
106 Flags
= PpData
.Flags
;
107 RequestConfirmed
= FALSE
;
109 switch (mTcgNvs
->PhysicalPresence
.Request
) {
110 case PHYSICAL_PRESENCE_ENABLE
:
111 case PHYSICAL_PRESENCE_DISABLE
:
112 case PHYSICAL_PRESENCE_ACTIVATE
:
113 case PHYSICAL_PRESENCE_DEACTIVATE
:
114 case PHYSICAL_PRESENCE_ENABLE_ACTIVATE
:
115 case PHYSICAL_PRESENCE_DEACTIVATE_DISABLE
:
116 case PHYSICAL_PRESENCE_SET_OWNER_INSTALL_TRUE
:
117 case PHYSICAL_PRESENCE_SET_OWNER_INSTALL_FALSE
:
118 case PHYSICAL_PRESENCE_ENABLE_ACTIVATE_OWNER_TRUE
:
119 case PHYSICAL_PRESENCE_DEACTIVATE_DISABLE_OWNER_FALSE
:
120 if ((Flags
& FLAG_NO_PPI_PROVISION
) != 0) {
121 RequestConfirmed
= TRUE
;
125 case PHYSICAL_PRESENCE_CLEAR
:
126 case PHYSICAL_PRESENCE_ENABLE_ACTIVATE_CLEAR
:
127 if ((Flags
& FLAG_NO_PPI_CLEAR
) != 0) {
128 RequestConfirmed
= TRUE
;
132 case PHYSICAL_PRESENCE_DEFERRED_PP_UNOWNERED_FIELD_UPGRADE
:
133 if ((Flags
& FLAG_NO_PPI_MAINTENANCE
) != 0) {
134 RequestConfirmed
= TRUE
;
138 case PHYSICAL_PRESENCE_ENABLE_ACTIVATE_CLEAR_ENABLE_ACTIVATE
:
139 case PHYSICAL_PRESENCE_CLEAR_ENABLE_ACTIVATE
:
140 if ((Flags
& FLAG_NO_PPI_CLEAR
) != 0 && (Flags
& FLAG_NO_PPI_PROVISION
) != 0) {
141 RequestConfirmed
= TRUE
;
145 case PHYSICAL_PRESENCE_SET_NO_PPI_PROVISION_FALSE
:
146 case PHYSICAL_PRESENCE_SET_NO_PPI_CLEAR_FALSE
:
147 case PHYSICAL_PRESENCE_SET_NO_PPI_MAINTENANCE_FALSE
:
148 case PHYSICAL_PRESENCE_NO_ACTION
:
149 RequestConfirmed
= TRUE
;
152 case PHYSICAL_PRESENCE_SET_OPERATOR_AUTH
:
154 // This command requires UI to prompt user for Auth data
156 mTcgNvs
->PhysicalPresence
.ReturnCode
= PP_REQUEST_NOT_IMPLEMENTED
;
160 if (RequestConfirmed
) {
161 mTcgNvs
->PhysicalPresence
.ReturnCode
= PP_REQUEST_ALLOWED_AND_PPUSER_NOT_REQUIRED
;
163 mTcgNvs
->PhysicalPresence
.ReturnCode
= PP_REQUEST_ALLOWED_AND_PPUSER_REQUIRED
;
172 Software SMI callback for MemoryClear which is called from ACPI method.
174 Caution: This function may receive untrusted input.
175 Variable and ACPINvs are external input, so this function will validate
176 its data structure to be valid value.
178 @param[in] DispatchHandle The unique handle assigned to this handler by SmiHandlerRegister().
179 @param[in] Context Points to an optional handler context which was specified when the
180 handler was registered.
181 @param[in, out] CommBuffer A pointer to a collection of data in memory that will
182 be conveyed from a non-SMM environment into an SMM environment.
183 @param[in, out] CommBufferSize The size of the CommBuffer.
185 @retval EFI_SUCCESS The interrupt was handled successfully.
190 MemoryClearCallback (
191 IN EFI_HANDLE DispatchHandle
,
192 IN CONST VOID
*Context
,
193 IN OUT VOID
*CommBuffer
,
194 IN OUT UINTN
*CommBufferSize
201 mTcgNvs
->MemoryClear
.ReturnCode
= MOR_REQUEST_SUCCESS
;
202 if (mTcgNvs
->MemoryClear
.Parameter
== ACPI_FUNCTION_DSM_MEMORY_CLEAR_INTERFACE
) {
203 MorControl
= (UINT8
) mTcgNvs
->MemoryClear
.Request
;
204 } else if (mTcgNvs
->MemoryClear
.Parameter
== ACPI_FUNCTION_PTS_CLEAR_MOR_BIT
) {
205 DataSize
= sizeof (UINT8
);
206 Status
= mSmmVariable
->SmmGetVariable (
207 MEMORY_OVERWRITE_REQUEST_VARIABLE_NAME
,
208 &gEfiMemoryOverwriteControlDataGuid
,
213 if (EFI_ERROR (Status
)) {
217 if (MOR_CLEAR_MEMORY_VALUE (MorControl
) == 0x0) {
220 MorControl
&= ~MOR_CLEAR_MEMORY_BIT_MASK
;
223 DataSize
= sizeof (UINT8
);
224 Status
= mSmmVariable
->SmmSetVariable (
225 MEMORY_OVERWRITE_REQUEST_VARIABLE_NAME
,
226 &gEfiMemoryOverwriteControlDataGuid
,
227 EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_RUNTIME_ACCESS
,
231 if (EFI_ERROR (Status
)) {
232 mTcgNvs
->MemoryClear
.ReturnCode
= MOR_REQUEST_GENERAL_FAILURE
;
239 Find the operation region in TCG ACPI table by given Name and Size,
240 and initialize it if the region is found.
242 @param[in, out] Table The TPM item in ACPI table.
243 @param[in] Name The name string to find in TPM table.
244 @param[in] Size The size of the region to find.
246 @return The allocated address for the found region.
251 EFI_ACPI_DESCRIPTION_HEADER
*Table
,
257 AML_OP_REGION_32_8
*OpRegion
;
258 EFI_PHYSICAL_ADDRESS MemoryAddress
;
260 MemoryAddress
= SIZE_4GB
- 1;
263 // Patch some pointers for the ASL code before loading the SSDT.
265 for (OpRegion
= (AML_OP_REGION_32_8
*) (Table
+ 1);
266 OpRegion
<= (AML_OP_REGION_32_8
*) ((UINT8
*) Table
+ Table
->Length
);
267 OpRegion
= (AML_OP_REGION_32_8
*) ((UINT8
*) OpRegion
+ 1)) {
268 if ((OpRegion
->OpRegionOp
== AML_EXT_REGION_OP
) &&
269 (OpRegion
->NameString
== Name
) &&
270 (OpRegion
->DWordPrefix
== AML_DWORD_PREFIX
) &&
271 (OpRegion
->BytePrefix
== AML_BYTE_PREFIX
)) {
273 Status
= gBS
->AllocatePages(AllocateMaxAddress
, EfiACPIMemoryNVS
, EFI_SIZE_TO_PAGES (Size
), &MemoryAddress
);
274 ASSERT_EFI_ERROR (Status
);
275 ZeroMem ((VOID
*)(UINTN
)MemoryAddress
, Size
);
276 OpRegion
->RegionOffset
= (UINT32
) (UINTN
) MemoryAddress
;
277 OpRegion
->RegionLen
= (UINT8
) Size
;
282 return (VOID
*) (UINTN
) MemoryAddress
;
286 Initialize and publish TPM items in ACPI table.
288 @retval EFI_SUCCESS The TCG ACPI table is published successfully.
289 @retval Others The TCG ACPI table is not published.
298 EFI_ACPI_TABLE_PROTOCOL
*AcpiTable
;
300 EFI_ACPI_DESCRIPTION_HEADER
*Table
;
303 Status
= GetSectionFromFv (
310 ASSERT_EFI_ERROR (Status
);
312 ASSERT (Table
->OemTableId
== SIGNATURE_64 ('T', 'c', 'g', 'T', 'a', 'b', 'l', 'e'));
313 mTcgNvs
= AssignOpRegion (Table
, SIGNATURE_32 ('T', 'N', 'V', 'S'), (UINT16
) sizeof (TCG_NVS
));
314 ASSERT (mTcgNvs
!= NULL
);
317 // Publish the TPM ACPI table
319 Status
= gBS
->LocateProtocol (&gEfiAcpiTableProtocolGuid
, NULL
, (VOID
**) &AcpiTable
);
320 ASSERT_EFI_ERROR (Status
);
323 Status
= AcpiTable
->InstallAcpiTable (
329 ASSERT_EFI_ERROR (Status
);
335 The driver's entry point.
337 It install callbacks for TPM physical presence and MemoryClear, and locate
338 SMM variable to be used in the callback function.
340 @param[in] ImageHandle The firmware allocated handle for the EFI image.
341 @param[in] SystemTable A pointer to the EFI System Table.
343 @retval EFI_SUCCESS The entry point is executed successfully.
344 @retval Others Some error occurs when executing this entry point.
350 IN EFI_HANDLE ImageHandle
,
351 IN EFI_SYSTEM_TABLE
*SystemTable
355 EFI_SMM_SW_DISPATCH2_PROTOCOL
*SwDispatch
;
356 EFI_SMM_SW_REGISTER_CONTEXT SwContext
;
359 Status
= PublishAcpiTable ();
360 ASSERT_EFI_ERROR (Status
);
363 // Get the Sw dispatch protocol and register SMI callback functions.
365 Status
= gSmst
->SmmLocateProtocol (&gEfiSmmSwDispatch2ProtocolGuid
, NULL
, (VOID
**)&SwDispatch
);
366 ASSERT_EFI_ERROR (Status
);
367 SwContext
.SwSmiInputValue
= (UINTN
) -1;
368 Status
= SwDispatch
->Register (SwDispatch
, PhysicalPresenceCallback
, &SwContext
, &SwHandle
);
369 ASSERT_EFI_ERROR (Status
);
370 if (EFI_ERROR (Status
)) {
373 mTcgNvs
->PhysicalPresence
.SoftwareSmi
= (UINT8
) SwContext
.SwSmiInputValue
;
375 SwContext
.SwSmiInputValue
= (UINTN
) -1;
376 Status
= SwDispatch
->Register (SwDispatch
, MemoryClearCallback
, &SwContext
, &SwHandle
);
377 ASSERT_EFI_ERROR (Status
);
378 if (EFI_ERROR (Status
)) {
381 mTcgNvs
->MemoryClear
.SoftwareSmi
= (UINT8
) SwContext
.SwSmiInputValue
;
384 // Locate SmmVariableProtocol.
386 Status
= gSmst
->SmmLocateProtocol (&gEfiSmmVariableProtocolGuid
, NULL
, (VOID
**)&mSmmVariable
);
387 ASSERT_EFI_ERROR (Status
);