]> git.proxmox.com Git - mirror_edk2.git/blob - SecurityPkg/Tcg/TcgSmm/TcgSmm.c
ArmPkg/ArmDmaLib: Fixed the calculation of the Base Address of the Buffer
[mirror_edk2.git] / SecurityPkg / Tcg / TcgSmm / TcgSmm.c
1 /** @file
2 It updates TPM items in ACPI table and registers SMI callback
3 functions for physical presence and ClearMemory.
4
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.
8
9 PhysicalPresenceCallback() and MemoryClearCallback() will receive untrusted input and do some check.
10
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
16
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.
19
20 **/
21
22 #include "TcgSmm.h"
23
24 EFI_SMM_VARIABLE_PROTOCOL *mSmmVariable;
25 TCG_NVS *mTcgNvs;
26
27 /**
28 Software SMI callback for TPM physical presence which is called from ACPI method.
29
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.
33
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.
40
41 @retval EFI_SUCCESS The interrupt was handled successfully.
42
43 **/
44 EFI_STATUS
45 EFIAPI
46 PhysicalPresenceCallback (
47 IN EFI_HANDLE DispatchHandle,
48 IN CONST VOID *Context,
49 IN OUT VOID *CommBuffer,
50 IN OUT UINTN *CommBufferSize
51 )
52 {
53 EFI_STATUS Status;
54 UINTN DataSize;
55 EFI_PHYSICAL_PRESENCE PpData;
56 UINT8 Flags;
57 BOOLEAN RequestConfirmed;
58
59 //
60 // Get the Physical Presence variable
61 //
62 DataSize = sizeof (EFI_PHYSICAL_PRESENCE);
63 Status = mSmmVariable->SmmGetVariable (
64 PHYSICAL_PRESENCE_VARIABLE,
65 &gEfiPhysicalPresenceGuid,
66 NULL,
67 &DataSize,
68 &PpData
69 );
70 if (EFI_ERROR (Status)) {
71 return EFI_SUCCESS;
72 }
73
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) {
81 //
82 // This command requires UI to prompt user for Auth data.
83 //
84 mTcgNvs->PhysicalPresence.ReturnCode = PP_SUBMIT_REQUEST_NOT_IMPLEMENTED;
85 return EFI_SUCCESS;
86 }
87
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,
95 DataSize,
96 &PpData
97 );
98 }
99
100 if (EFI_ERROR (Status)) {
101 mTcgNvs->PhysicalPresence.ReturnCode = PP_SUBMIT_REQUEST_GENERAL_FAILURE;
102 return EFI_SUCCESS;
103 }
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;
108
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;
122 }
123 break;
124
125 case PHYSICAL_PRESENCE_CLEAR:
126 case PHYSICAL_PRESENCE_ENABLE_ACTIVATE_CLEAR:
127 if ((Flags & FLAG_NO_PPI_CLEAR) != 0) {
128 RequestConfirmed = TRUE;
129 }
130 break;
131
132 case PHYSICAL_PRESENCE_DEFERRED_PP_UNOWNERED_FIELD_UPGRADE:
133 if ((Flags & FLAG_NO_PPI_MAINTENANCE) != 0) {
134 RequestConfirmed = TRUE;
135 }
136 break;
137
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;
142 }
143 break;
144
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;
150 break;
151
152 case PHYSICAL_PRESENCE_SET_OPERATOR_AUTH:
153 //
154 // This command requires UI to prompt user for Auth data
155 //
156 mTcgNvs->PhysicalPresence.ReturnCode = PP_REQUEST_NOT_IMPLEMENTED;
157 return EFI_SUCCESS;
158 }
159
160 if (RequestConfirmed) {
161 mTcgNvs->PhysicalPresence.ReturnCode = PP_REQUEST_ALLOWED_AND_PPUSER_NOT_REQUIRED;
162 } else {
163 mTcgNvs->PhysicalPresence.ReturnCode = PP_REQUEST_ALLOWED_AND_PPUSER_REQUIRED;
164 }
165 }
166
167 return EFI_SUCCESS;
168 }
169
170
171 /**
172 Software SMI callback for MemoryClear which is called from ACPI method.
173
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.
177
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.
184
185 @retval EFI_SUCCESS The interrupt was handled successfully.
186
187 **/
188 EFI_STATUS
189 EFIAPI
190 MemoryClearCallback (
191 IN EFI_HANDLE DispatchHandle,
192 IN CONST VOID *Context,
193 IN OUT VOID *CommBuffer,
194 IN OUT UINTN *CommBufferSize
195 )
196 {
197 EFI_STATUS Status;
198 UINTN DataSize;
199 UINT8 MorControl;
200
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,
209 NULL,
210 &DataSize,
211 &MorControl
212 );
213 if (EFI_ERROR (Status)) {
214 return EFI_SUCCESS;
215 }
216
217 if (MOR_CLEAR_MEMORY_VALUE (MorControl) == 0x0) {
218 return EFI_SUCCESS;
219 }
220 MorControl &= ~MOR_CLEAR_MEMORY_BIT_MASK;
221 }
222
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,
228 DataSize,
229 &MorControl
230 );
231 if (EFI_ERROR (Status)) {
232 mTcgNvs->MemoryClear.ReturnCode = MOR_REQUEST_GENERAL_FAILURE;
233 }
234
235 return EFI_SUCCESS;
236 }
237
238 /**
239 Find the operation region in TCG ACPI table by given Name and Size,
240 and initialize it if the region is found.
241
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.
245
246 @return The allocated address for the found region.
247
248 **/
249 VOID *
250 AssignOpRegion (
251 EFI_ACPI_DESCRIPTION_HEADER *Table,
252 UINT32 Name,
253 UINT16 Size
254 )
255 {
256 EFI_STATUS Status;
257 AML_OP_REGION_32_8 *OpRegion;
258 EFI_PHYSICAL_ADDRESS MemoryAddress;
259
260 MemoryAddress = SIZE_4GB - 1;
261
262 //
263 // Patch some pointers for the ASL code before loading the SSDT.
264 //
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)) {
272
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;
278 break;
279 }
280 }
281
282 return (VOID *) (UINTN) MemoryAddress;
283 }
284
285 /**
286 Initialize and publish TPM items in ACPI table.
287
288 @retval EFI_SUCCESS The TCG ACPI table is published successfully.
289 @retval Others The TCG ACPI table is not published.
290
291 **/
292 EFI_STATUS
293 PublishAcpiTable (
294 VOID
295 )
296 {
297 EFI_STATUS Status;
298 EFI_ACPI_TABLE_PROTOCOL *AcpiTable;
299 UINTN TableKey;
300 EFI_ACPI_DESCRIPTION_HEADER *Table;
301 UINTN TableSize;
302
303 Status = GetSectionFromFv (
304 &gEfiCallerIdGuid,
305 EFI_SECTION_RAW,
306 0,
307 (VOID **) &Table,
308 &TableSize
309 );
310 ASSERT_EFI_ERROR (Status);
311
312
313 //
314 // Measure to PCR[0] with event EV_POST_CODE ACPI DATA
315 //
316 TpmMeasureAndLogData(
317 0,
318 EV_POST_CODE,
319 EV_POSTCODE_INFO_ACPI_DATA,
320 ACPI_DATA_LEN,
321 Table,
322 TableSize
323 );
324
325
326 ASSERT (Table->OemTableId == SIGNATURE_64 ('T', 'c', 'g', 'T', 'a', 'b', 'l', 'e'));
327 mTcgNvs = AssignOpRegion (Table, SIGNATURE_32 ('T', 'N', 'V', 'S'), (UINT16) sizeof (TCG_NVS));
328 ASSERT (mTcgNvs != NULL);
329
330 //
331 // Publish the TPM ACPI table
332 //
333 Status = gBS->LocateProtocol (&gEfiAcpiTableProtocolGuid, NULL, (VOID **) &AcpiTable);
334 ASSERT_EFI_ERROR (Status);
335
336 TableKey = 0;
337 Status = AcpiTable->InstallAcpiTable (
338 AcpiTable,
339 Table,
340 TableSize,
341 &TableKey
342 );
343 ASSERT_EFI_ERROR (Status);
344
345 return Status;
346 }
347
348 /**
349 The driver's entry point.
350
351 It install callbacks for TPM physical presence and MemoryClear, and locate
352 SMM variable to be used in the callback function.
353
354 @param[in] ImageHandle The firmware allocated handle for the EFI image.
355 @param[in] SystemTable A pointer to the EFI System Table.
356
357 @retval EFI_SUCCESS The entry point is executed successfully.
358 @retval Others Some error occurs when executing this entry point.
359
360 **/
361 EFI_STATUS
362 EFIAPI
363 InitializeTcgSmm (
364 IN EFI_HANDLE ImageHandle,
365 IN EFI_SYSTEM_TABLE *SystemTable
366 )
367 {
368 EFI_STATUS Status;
369 EFI_SMM_SW_DISPATCH2_PROTOCOL *SwDispatch;
370 EFI_SMM_SW_REGISTER_CONTEXT SwContext;
371 EFI_HANDLE SwHandle;
372
373 Status = PublishAcpiTable ();
374 ASSERT_EFI_ERROR (Status);
375
376 //
377 // Get the Sw dispatch protocol and register SMI callback functions.
378 //
379 Status = gSmst->SmmLocateProtocol (&gEfiSmmSwDispatch2ProtocolGuid, NULL, (VOID**)&SwDispatch);
380 ASSERT_EFI_ERROR (Status);
381 SwContext.SwSmiInputValue = (UINTN) -1;
382 Status = SwDispatch->Register (SwDispatch, PhysicalPresenceCallback, &SwContext, &SwHandle);
383 ASSERT_EFI_ERROR (Status);
384 if (EFI_ERROR (Status)) {
385 return Status;
386 }
387 mTcgNvs->PhysicalPresence.SoftwareSmi = (UINT8) SwContext.SwSmiInputValue;
388
389 SwContext.SwSmiInputValue = (UINTN) -1;
390 Status = SwDispatch->Register (SwDispatch, MemoryClearCallback, &SwContext, &SwHandle);
391 ASSERT_EFI_ERROR (Status);
392 if (EFI_ERROR (Status)) {
393 return Status;
394 }
395 mTcgNvs->MemoryClear.SoftwareSmi = (UINT8) SwContext.SwSmiInputValue;
396
397 //
398 // Locate SmmVariableProtocol.
399 //
400 Status = gSmst->SmmLocateProtocol (&gEfiSmmVariableProtocolGuid, NULL, (VOID**)&mSmmVariable);
401 ASSERT_EFI_ERROR (Status);
402
403 return EFI_SUCCESS;
404 }
405