]> git.proxmox.com Git - mirror_edk2.git/blame_incremental - SecurityPkg/Tcg/TcgSmm/TcgSmm.c
EFI_STATUS_CODE_DATA_MAX_SIZE is just for the maximum size of an EFI_DEBUG_INFO struc...
[mirror_edk2.git] / SecurityPkg / Tcg / TcgSmm / TcgSmm.c
... / ...
CommitLineData
1/** @file\r
2 It updates TPM items in ACPI table and registers SMI callback\r
3 functions for physical presence and ClearMemory.\r
4\r
5Copyright (c) 2011 - 2012, Intel Corporation. All rights reserved.<BR>\r
6This program and the accompanying materials \r
7are licensed and made available under the terms and conditions of the BSD License \r
8which accompanies this distribution. The full text of the license may be found at \r
9http://opensource.org/licenses/bsd-license.php\r
10\r
11THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r
12WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
13\r
14**/\r
15\r
16#include "TcgSmm.h"\r
17\r
18EFI_SMM_VARIABLE_PROTOCOL *mSmmVariable;\r
19TCG_NVS *mTcgNvs;\r
20\r
21/**\r
22 Software SMI callback for TPM physical presence which is called from ACPI method.\r
23\r
24 @param[in] DispatchHandle The unique handle assigned to this handler by SmiHandlerRegister().\r
25 @param[in] Context Points to an optional handler context which was specified when the\r
26 handler was registered.\r
27 @param[in, out] CommBuffer A pointer to a collection of data in memory that will\r
28 be conveyed from a non-SMM environment into an SMM environment.\r
29 @param[in, out] CommBufferSize The size of the CommBuffer.\r
30\r
31 @retval EFI_SUCCESS The interrupt was handled successfully.\r
32\r
33**/\r
34EFI_STATUS\r
35EFIAPI\r
36PhysicalPresenceCallback (\r
37 IN EFI_HANDLE DispatchHandle,\r
38 IN CONST VOID *Context,\r
39 IN OUT VOID *CommBuffer,\r
40 IN OUT UINTN *CommBufferSize\r
41 )\r
42{\r
43 EFI_STATUS Status;\r
44 UINTN DataSize;\r
45 EFI_PHYSICAL_PRESENCE PpData;\r
46 UINT8 Flags;\r
47 BOOLEAN RequestConfirmed;\r
48\r
49 //\r
50 // Get the Physical Presence variable\r
51 //\r
52 DataSize = sizeof (EFI_PHYSICAL_PRESENCE);\r
53 Status = mSmmVariable->SmmGetVariable (\r
54 PHYSICAL_PRESENCE_VARIABLE,\r
55 &gEfiPhysicalPresenceGuid,\r
56 NULL,\r
57 &DataSize,\r
58 &PpData\r
59 );\r
60 if (EFI_ERROR (Status)) {\r
61 return EFI_SUCCESS;\r
62 }\r
63\r
64 DEBUG ((EFI_D_INFO, "[TPM] PP callback, Parameter = %x\n", mTcgNvs->PhysicalPresence.Parameter));\r
65 if (mTcgNvs->PhysicalPresence.Parameter == ACPI_FUNCTION_RETURN_REQUEST_RESPONSE_TO_OS) {\r
66 mTcgNvs->PhysicalPresence.LastRequest = PpData.LastPPRequest;\r
67 mTcgNvs->PhysicalPresence.Response = PpData.PPResponse;\r
68 } else if ((mTcgNvs->PhysicalPresence.Parameter == ACPI_FUNCTION_SUBMIT_REQUEST_TO_BIOS) \r
69 || (mTcgNvs->PhysicalPresence.Parameter == ACPI_FUNCTION_SUBMIT_REQUEST_TO_BIOS_2)) {\r
70 if (mTcgNvs->PhysicalPresence.Request == PHYSICAL_PRESENCE_SET_OPERATOR_AUTH) {\r
71 //\r
72 // This command requires UI to prompt user for Auth data.\r
73 //\r
74 mTcgNvs->PhysicalPresence.ReturnCode = PP_SUBMIT_REQUEST_NOT_IMPLEMENTED;\r
75 return EFI_SUCCESS;\r
76 }\r
77\r
78 if (PpData.PPRequest != mTcgNvs->PhysicalPresence.Request) {\r
79 PpData.PPRequest = (UINT8) mTcgNvs->PhysicalPresence.Request;\r
80 DataSize = sizeof (EFI_PHYSICAL_PRESENCE);\r
81 Status = mSmmVariable->SmmSetVariable (\r
82 PHYSICAL_PRESENCE_VARIABLE,\r
83 &gEfiPhysicalPresenceGuid,\r
84 EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,\r
85 DataSize,\r
86 &PpData\r
87 );\r
88 }\r
89\r
90 if (EFI_ERROR (Status)) { \r
91 mTcgNvs->PhysicalPresence.ReturnCode = PP_SUBMIT_REQUEST_GENERAL_FAILURE;\r
92 return EFI_SUCCESS;\r
93 }\r
94 mTcgNvs->PhysicalPresence.ReturnCode = PP_SUBMIT_REQUEST_SUCCESS;\r
95 } else if (mTcgNvs->PhysicalPresence.Parameter == ACPI_FUNCTION_GET_USER_CONFIRMATION_STATUS_FOR_REQUEST) {\r
96 Flags = PpData.Flags; \r
97 RequestConfirmed = FALSE;\r
98\r
99 switch (mTcgNvs->PhysicalPresence.Request) {\r
100 case PHYSICAL_PRESENCE_ENABLE:\r
101 case PHYSICAL_PRESENCE_DISABLE:\r
102 case PHYSICAL_PRESENCE_ACTIVATE:\r
103 case PHYSICAL_PRESENCE_DEACTIVATE:\r
104 case PHYSICAL_PRESENCE_ENABLE_ACTIVATE:\r
105 case PHYSICAL_PRESENCE_DEACTIVATE_DISABLE:\r
106 case PHYSICAL_PRESENCE_SET_OWNER_INSTALL_TRUE:\r
107 case PHYSICAL_PRESENCE_SET_OWNER_INSTALL_FALSE:\r
108 case PHYSICAL_PRESENCE_ENABLE_ACTIVATE_OWNER_TRUE:\r
109 case PHYSICAL_PRESENCE_DEACTIVATE_DISABLE_OWNER_FALSE:\r
110 if ((Flags & FLAG_NO_PPI_PROVISION) != 0) {\r
111 RequestConfirmed = TRUE;\r
112 }\r
113 break;\r
114\r
115 case PHYSICAL_PRESENCE_CLEAR:\r
116 case PHYSICAL_PRESENCE_ENABLE_ACTIVATE_CLEAR:\r
117 if ((Flags & FLAG_NO_PPI_CLEAR) != 0) {\r
118 RequestConfirmed = TRUE;\r
119 }\r
120 break;\r
121\r
122 case PHYSICAL_PRESENCE_DEFERRED_PP_UNOWNERED_FIELD_UPGRADE:\r
123 if ((Flags & FLAG_NO_PPI_MAINTENANCE) != 0) {\r
124 RequestConfirmed = TRUE;\r
125 }\r
126 break;\r
127\r
128 case PHYSICAL_PRESENCE_ENABLE_ACTIVATE_CLEAR_ENABLE_ACTIVATE:\r
129 case PHYSICAL_PRESENCE_CLEAR_ENABLE_ACTIVATE:\r
130 if ((Flags & FLAG_NO_PPI_CLEAR) != 0 && (Flags & FLAG_NO_PPI_PROVISION) != 0) {\r
131 RequestConfirmed = TRUE;\r
132 }\r
133 break; \r
134\r
135 case PHYSICAL_PRESENCE_SET_NO_PPI_PROVISION_FALSE:\r
136 case PHYSICAL_PRESENCE_SET_NO_PPI_CLEAR_FALSE:\r
137 case PHYSICAL_PRESENCE_SET_NO_PPI_MAINTENANCE_FALSE:\r
138 case PHYSICAL_PRESENCE_NO_ACTION:\r
139 RequestConfirmed = TRUE;\r
140 break;\r
141\r
142 case PHYSICAL_PRESENCE_SET_OPERATOR_AUTH:\r
143 //\r
144 // This command requires UI to prompt user for Auth data\r
145 //\r
146 mTcgNvs->PhysicalPresence.ReturnCode = PP_REQUEST_NOT_IMPLEMENTED; \r
147 return EFI_SUCCESS;\r
148 }\r
149\r
150 if (RequestConfirmed) {\r
151 mTcgNvs->PhysicalPresence.ReturnCode = PP_REQUEST_ALLOWED_AND_PPUSER_NOT_REQUIRED;\r
152 } else {\r
153 mTcgNvs->PhysicalPresence.ReturnCode = PP_REQUEST_ALLOWED_AND_PPUSER_REQUIRED;\r
154 } \r
155 } \r
156\r
157 return EFI_SUCCESS;\r
158}\r
159\r
160\r
161/**\r
162 Software SMI callback for MemoryClear which is called from ACPI method.\r
163\r
164 @param[in] DispatchHandle The unique handle assigned to this handler by SmiHandlerRegister().\r
165 @param[in] Context Points to an optional handler context which was specified when the\r
166 handler was registered.\r
167 @param[in, out] CommBuffer A pointer to a collection of data in memory that will\r
168 be conveyed from a non-SMM environment into an SMM environment.\r
169 @param[in, out] CommBufferSize The size of the CommBuffer.\r
170\r
171 @retval EFI_SUCCESS The interrupt was handled successfully.\r
172\r
173**/\r
174EFI_STATUS\r
175EFIAPI\r
176MemoryClearCallback (\r
177 IN EFI_HANDLE DispatchHandle,\r
178 IN CONST VOID *Context,\r
179 IN OUT VOID *CommBuffer,\r
180 IN OUT UINTN *CommBufferSize\r
181 )\r
182{\r
183 EFI_STATUS Status;\r
184 UINTN DataSize;\r
185 UINT8 MorControl;\r
186\r
187 mTcgNvs->MemoryClear.ReturnCode = MOR_REQUEST_SUCCESS;\r
188 if (mTcgNvs->MemoryClear.Parameter == ACPI_FUNCTION_DSM_MEMORY_CLEAR_INTERFACE) {\r
189 MorControl = (UINT8) mTcgNvs->MemoryClear.Request;\r
190 } else if (mTcgNvs->MemoryClear.Parameter == ACPI_FUNCTION_PTS_CLEAR_MOR_BIT) {\r
191 DataSize = sizeof (UINT8);\r
192 Status = mSmmVariable->SmmGetVariable (\r
193 MEMORY_OVERWRITE_REQUEST_VARIABLE_NAME,\r
194 &gEfiMemoryOverwriteControlDataGuid,\r
195 NULL,\r
196 &DataSize,\r
197 &MorControl\r
198 );\r
199 if (EFI_ERROR (Status)) {\r
200 return EFI_SUCCESS;\r
201 }\r
202\r
203 if (MOR_CLEAR_MEMORY_VALUE (MorControl) == 0x0) {\r
204 return EFI_SUCCESS;\r
205 }\r
206 MorControl &= ~MOR_CLEAR_MEMORY_BIT_MASK;\r
207 }\r
208\r
209 DataSize = sizeof (UINT8);\r
210 Status = mSmmVariable->SmmSetVariable (\r
211 MEMORY_OVERWRITE_REQUEST_VARIABLE_NAME,\r
212 &gEfiMemoryOverwriteControlDataGuid,\r
213 EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,\r
214 DataSize,\r
215 &MorControl\r
216 );\r
217 if (EFI_ERROR (Status)) { \r
218 mTcgNvs->MemoryClear.ReturnCode = MOR_REQUEST_GENERAL_FAILURE;\r
219 }\r
220\r
221 return EFI_SUCCESS;\r
222}\r
223\r
224/**\r
225 Find the operation region in TCG ACPI table by given Name and Size,\r
226 and initialize it if the region is found.\r
227\r
228 @param[in, out] Table The TPM item in ACPI table.\r
229 @param[in] Name The name string to find in TPM table.\r
230 @param[in] Size The size of the region to find.\r
231\r
232 @return The allocated address for the found region.\r
233\r
234**/\r
235VOID *\r
236AssignOpRegion (\r
237 EFI_ACPI_DESCRIPTION_HEADER *Table,\r
238 UINT32 Name,\r
239 UINT16 Size\r
240 )\r
241{\r
242 EFI_STATUS Status;\r
243 AML_OP_REGION_32_8 *OpRegion;\r
244 EFI_PHYSICAL_ADDRESS MemoryAddress;\r
245\r
246 MemoryAddress = SIZE_4GB - 1;\r
247\r
248 //\r
249 // Patch some pointers for the ASL code before loading the SSDT.\r
250 //\r
251 for (OpRegion = (AML_OP_REGION_32_8 *) (Table + 1);\r
252 OpRegion <= (AML_OP_REGION_32_8 *) ((UINT8 *) Table + Table->Length);\r
253 OpRegion = (AML_OP_REGION_32_8 *) ((UINT8 *) OpRegion + 1)) {\r
254 if ((OpRegion->OpRegionOp == AML_EXT_REGION_OP) && \r
255 (OpRegion->NameString == Name) &&\r
256 (OpRegion->DWordPrefix == AML_DWORD_PREFIX) &&\r
257 (OpRegion->BytePrefix == AML_BYTE_PREFIX)) {\r
258\r
259 Status = gBS->AllocatePages(AllocateMaxAddress, EfiACPIMemoryNVS, EFI_SIZE_TO_PAGES (Size), &MemoryAddress);\r
260 ASSERT_EFI_ERROR (Status);\r
261 ZeroMem ((VOID *)(UINTN)MemoryAddress, Size);\r
262 OpRegion->RegionOffset = (UINT32) (UINTN) MemoryAddress;\r
263 OpRegion->RegionLen = (UINT8) Size;\r
264 break;\r
265 }\r
266 }\r
267\r
268 return (VOID *) (UINTN) MemoryAddress;\r
269}\r
270\r
271/**\r
272 Initialize and publish TPM items in ACPI table.\r
273\r
274 @retval EFI_SUCCESS The TCG ACPI table is published successfully.\r
275 @retval Others The TCG ACPI table is not published.\r
276\r
277**/\r
278EFI_STATUS\r
279PublishAcpiTable (\r
280 VOID\r
281 )\r
282{\r
283 EFI_STATUS Status;\r
284 EFI_ACPI_TABLE_PROTOCOL *AcpiTable;\r
285 UINTN TableKey;\r
286 EFI_ACPI_DESCRIPTION_HEADER *Table;\r
287 UINTN TableSize;\r
288\r
289 Status = GetSectionFromFv (\r
290 &gEfiCallerIdGuid,\r
291 EFI_SECTION_RAW,\r
292 0,\r
293 (VOID **) &Table,\r
294 &TableSize\r
295 );\r
296 ASSERT_EFI_ERROR (Status);\r
297\r
298 ASSERT (Table->OemTableId == SIGNATURE_64 ('T', 'c', 'g', 'T', 'a', 'b', 'l', 'e'));\r
299 mTcgNvs = AssignOpRegion (Table, SIGNATURE_32 ('T', 'N', 'V', 'S'), (UINT16) sizeof (TCG_NVS));\r
300 ASSERT (mTcgNvs != NULL);\r
301\r
302 //\r
303 // Publish the TPM ACPI table\r
304 //\r
305 Status = gBS->LocateProtocol (&gEfiAcpiTableProtocolGuid, NULL, (VOID **) &AcpiTable);\r
306 ASSERT_EFI_ERROR (Status);\r
307\r
308 TableKey = 0;\r
309 Status = AcpiTable->InstallAcpiTable (\r
310 AcpiTable,\r
311 Table,\r
312 TableSize,\r
313 &TableKey\r
314 );\r
315 ASSERT_EFI_ERROR (Status);\r
316\r
317 return Status;\r
318}\r
319\r
320/**\r
321 The driver's entry point.\r
322\r
323 It install callbacks for TPM physical presence and MemoryClear, and locate \r
324 SMM variable to be used in the callback function.\r
325\r
326 @param[in] ImageHandle The firmware allocated handle for the EFI image. \r
327 @param[in] SystemTable A pointer to the EFI System Table.\r
328 \r
329 @retval EFI_SUCCESS The entry point is executed successfully.\r
330 @retval Others Some error occurs when executing this entry point.\r
331\r
332**/\r
333EFI_STATUS\r
334EFIAPI\r
335InitializeTcgSmm (\r
336 IN EFI_HANDLE ImageHandle,\r
337 IN EFI_SYSTEM_TABLE *SystemTable\r
338 )\r
339{\r
340 EFI_STATUS Status;\r
341 EFI_SMM_SW_DISPATCH2_PROTOCOL *SwDispatch;\r
342 EFI_SMM_SW_REGISTER_CONTEXT SwContext;\r
343 EFI_HANDLE SwHandle;\r
344\r
345 Status = PublishAcpiTable ();\r
346 ASSERT_EFI_ERROR (Status);\r
347\r
348 //\r
349 // Get the Sw dispatch protocol and register SMI callback functions.\r
350 //\r
351 Status = gSmst->SmmLocateProtocol (&gEfiSmmSwDispatch2ProtocolGuid, NULL, (VOID**)&SwDispatch);\r
352 ASSERT_EFI_ERROR (Status);\r
353 SwContext.SwSmiInputValue = (UINTN) -1;\r
354 Status = SwDispatch->Register (SwDispatch, PhysicalPresenceCallback, &SwContext, &SwHandle);\r
355 ASSERT_EFI_ERROR (Status);\r
356 if (EFI_ERROR (Status)) {\r
357 return Status;\r
358 }\r
359 mTcgNvs->PhysicalPresence.SoftwareSmi = (UINT8) SwContext.SwSmiInputValue;\r
360\r
361 SwContext.SwSmiInputValue = (UINTN) -1;\r
362 Status = SwDispatch->Register (SwDispatch, MemoryClearCallback, &SwContext, &SwHandle);\r
363 ASSERT_EFI_ERROR (Status);\r
364 if (EFI_ERROR (Status)) {\r
365 return Status;\r
366 }\r
367 mTcgNvs->MemoryClear.SoftwareSmi = (UINT8) SwContext.SwSmiInputValue;\r
368 \r
369 //\r
370 // Locate SmmVariableProtocol.\r
371 //\r
372 Status = gSmst->SmmLocateProtocol (&gEfiSmmVariableProtocolGuid, NULL, (VOID**)&mSmmVariable);\r
373 ASSERT_EFI_ERROR (Status);\r
374\r
375 return EFI_SUCCESS;\r
376}\r
377\r