]> git.proxmox.com Git - mirror_edk2.git/blame - UefiCpuPkg/PiSmmCommunication/PiSmmCommunicationPei.c
UefiCpuPkg CpuCommFeaturesLib: Fix GP fault issue about ProcTrace
[mirror_edk2.git] / UefiCpuPkg / PiSmmCommunication / PiSmmCommunicationPei.c
CommitLineData
b3dc26ed
MK
1/** @file\r
2PiSmmCommunication PEI Driver.\r
3\r
4Copyright (c) 2010 - 2015, Intel Corporation. All rights reserved.<BR>\r
0acd8697 5SPDX-License-Identifier: BSD-2-Clause-Patent\r
b3dc26ed
MK
6\r
7**/\r
8\r
9#include <PiPei.h>\r
10#include <PiDxe.h>\r
11#include <PiSmm.h>\r
12#include <Library/PeiServicesTablePointerLib.h>\r
13#include <Library/PeiServicesLib.h>\r
14#include <Library/BaseLib.h>\r
15#include <Library/BaseMemoryLib.h>\r
16#include <Library/HobLib.h>\r
17#include <Library/DebugLib.h>\r
18#include <Protocol/SmmCommunication.h>\r
19#include <Ppi/SmmCommunication.h>\r
20#include <Ppi/SmmAccess.h>\r
21#include <Ppi/SmmControl.h>\r
22#include <Guid/AcpiS3Context.h>\r
23\r
24#include "PiSmmCommunicationPrivate.h"\r
25\r
26/**\r
27 the whole picture is below:\r
28\r
29 +----------------------------------+\r
30 | ACPI_VARIABLE_HOB |\r
31 | SmramDescriptor | <- DRAM\r
32 | CpuStart |---\r
33 +----------------------------------+ |\r
34 |\r
35 +----------------------------------+<--\r
36 | SMM_S3_RESUME_STATE |\r
37 | Signature | <- SMRAM\r
38 | Smst |---\r
39 +----------------------------------+ |\r
40 |\r
41 +----------------------------------+<--\r
42 | EFI_SMM_SYSTEM_TABLE2 |\r
43 | NumberOfTableEntries | <- SMRAM\r
44 | SmmConfigurationTable |---\r
45 +----------------------------------+ |\r
46 |\r
47 +----------------------------------+<--\r
48 | EFI_SMM_COMMUNICATION_CONTEXT |\r
49 | SwSmiNumber | <- SMRAM\r
50 | BufferPtrAddress |----------------\r
51 +----------------------------------+ |\r
52 |\r
53 +----------------------------------+ |\r
54 | EFI_SMM_COMMUNICATION_ACPI_TABLE | |\r
55 | SwSmiNumber | <- AcpiTable |\r
56 | BufferPtrAddress |--- |\r
57 +----------------------------------+ | |\r
58 | |\r
59 +----------------------------------+<---------------\r
60 | Communication Buffer Pointer | <- AcpiNvs\r
61 +----------------------------------+---\r
62 |\r
63 +----------------------------------+<--\r
64 | EFI_SMM_COMMUNICATE_HEADER |\r
65 | HeaderGuid | <- DRAM\r
66 | MessageLength |\r
67 +----------------------------------+\r
68\r
69**/\r
70\r
71#if defined (MDE_CPU_IA32)\r
72typedef struct {\r
73 EFI_TABLE_HEADER Hdr;\r
74 UINT64 SmmFirmwareVendor;\r
75 UINT64 SmmFirmwareRevision;\r
76 UINT64 SmmInstallConfigurationTable;\r
77 UINT64 SmmIoMemRead;\r
78 UINT64 SmmIoMemWrite;\r
79 UINT64 SmmIoIoRead;\r
80 UINT64 SmmIoIoWrite;\r
81 UINT64 SmmAllocatePool;\r
82 UINT64 SmmFreePool;\r
83 UINT64 SmmAllocatePages;\r
84 UINT64 SmmFreePages;\r
85 UINT64 SmmStartupThisAp;\r
86 UINT64 CurrentlyExecutingCpu;\r
87 UINT64 NumberOfCpus;\r
88 UINT64 CpuSaveStateSize;\r
89 UINT64 CpuSaveState;\r
90 UINT64 NumberOfTableEntries;\r
91 UINT64 SmmConfigurationTable;\r
92} EFI_SMM_SYSTEM_TABLE2_64;\r
93\r
94typedef struct {\r
95 EFI_GUID VendorGuid;\r
96 UINT64 VendorTable;\r
97} EFI_CONFIGURATION_TABLE64;\r
98#endif\r
99\r
100#if defined (MDE_CPU_X64)\r
101typedef EFI_SMM_SYSTEM_TABLE2 EFI_SMM_SYSTEM_TABLE2_64;\r
102typedef EFI_CONFIGURATION_TABLE EFI_CONFIGURATION_TABLE64;\r
103#endif\r
104\r
105/**\r
106 Communicates with a registered handler.\r
107\r
108 This function provides a service to send and receive messages from a registered UEFI service.\r
109\r
110 @param[in] This The EFI_PEI_SMM_COMMUNICATION_PPI instance.\r
111 @param[in, out] CommBuffer A pointer to the buffer to convey into SMRAM.\r
112 @param[in, out] CommSize The size of the data buffer being passed in.On exit, the size of data\r
113 being returned. Zero if the handler does not wish to reply with any data.\r
114\r
115 @retval EFI_SUCCESS The message was successfully posted.\r
116 @retval EFI_INVALID_PARAMETER The CommBuffer was NULL.\r
117 @retval EFI_NOT_STARTED The service is NOT started.\r
118**/\r
119EFI_STATUS\r
120EFIAPI\r
121Communicate (\r
122 IN CONST EFI_PEI_SMM_COMMUNICATION_PPI *This,\r
123 IN OUT VOID *CommBuffer,\r
124 IN OUT UINTN *CommSize\r
125 );\r
126\r
127EFI_PEI_SMM_COMMUNICATION_PPI mSmmCommunicationPpi = { Communicate };\r
128\r
129EFI_PEI_PPI_DESCRIPTOR mPpiList = {\r
130 (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),\r
131 &gEfiPeiSmmCommunicationPpiGuid,\r
132 &mSmmCommunicationPpi\r
133};\r
134\r
135/**\r
136 Get SMM communication context.\r
137\r
138 @return SMM communication context.\r
139**/\r
140EFI_SMM_COMMUNICATION_CONTEXT *\r
141GetCommunicationContext (\r
142 VOID\r
143 )\r
144{\r
145 EFI_HOB_GUID_TYPE *GuidHob;\r
146 EFI_SMM_COMMUNICATION_CONTEXT *SmmCommunicationContext;\r
147\r
148 GuidHob = GetFirstGuidHob (&gEfiPeiSmmCommunicationPpiGuid);\r
149 ASSERT (GuidHob != NULL);\r
150\r
151 SmmCommunicationContext = (EFI_SMM_COMMUNICATION_CONTEXT *)GET_GUID_HOB_DATA (GuidHob);\r
152\r
153 return SmmCommunicationContext;\r
154}\r
155\r
156/**\r
157 Set SMM communication context.\r
158\r
159 @param SmmCommunicationContext SMM communication context.\r
160**/\r
161VOID\r
162SetCommunicationContext (\r
163 IN EFI_SMM_COMMUNICATION_CONTEXT *SmmCommunicationContext\r
164 )\r
165{\r
166 EFI_PEI_HOB_POINTERS Hob;\r
167 UINTN BufferSize;\r
168\r
169 BufferSize = sizeof (*SmmCommunicationContext);\r
170 Hob.Raw = BuildGuidHob (\r
171 &gEfiPeiSmmCommunicationPpiGuid,\r
172 BufferSize\r
173 );\r
174 ASSERT (Hob.Raw);\r
175\r
176 CopyMem ((VOID *)Hob.Raw, SmmCommunicationContext, sizeof(*SmmCommunicationContext));\r
177}\r
178\r
179/**\r
180 Get VendorTable by VendorGuid in Smst.\r
181\r
182 @param Signature Signature of SMM_S3_RESUME_STATE\r
183 @param Smst SMM system table\r
184 @param VendorGuid vendor guid\r
185\r
186 @return vendor table.\r
187**/\r
188VOID *\r
189InternalSmstGetVendorTableByGuid (\r
190 IN UINT64 Signature,\r
191 IN EFI_SMM_SYSTEM_TABLE2 *Smst,\r
192 IN EFI_GUID *VendorGuid\r
193 )\r
194{\r
195 EFI_CONFIGURATION_TABLE *SmmConfigurationTable;\r
196 UINTN NumberOfTableEntries;\r
197 UINTN Index;\r
198 EFI_SMM_SYSTEM_TABLE2_64 *Smst64;\r
199 EFI_CONFIGURATION_TABLE64 *SmmConfigurationTable64;\r
200\r
201 if ((sizeof(UINTN) == sizeof(UINT32)) && (Signature == SMM_S3_RESUME_SMM_64)) {\r
202 //\r
203 // 32 PEI + 64 DXE\r
204 //\r
205 Smst64 = (EFI_SMM_SYSTEM_TABLE2_64 *)Smst;\r
206 DEBUG ((EFI_D_INFO, "InitCommunicationContext - SmmConfigurationTable: %x\n", Smst64->SmmConfigurationTable));\r
207 DEBUG ((EFI_D_INFO, "InitCommunicationContext - NumberOfTableEntries: %x\n", Smst64->NumberOfTableEntries));\r
208 SmmConfigurationTable64 = (EFI_CONFIGURATION_TABLE64 *)(UINTN)Smst64->SmmConfigurationTable;\r
209 NumberOfTableEntries = (UINTN)Smst64->NumberOfTableEntries;\r
210 for (Index = 0; Index < NumberOfTableEntries; Index++) {\r
211 if (CompareGuid (&SmmConfigurationTable64[Index].VendorGuid, VendorGuid)) {\r
212 return (VOID *)(UINTN)SmmConfigurationTable64[Index].VendorTable;\r
213 }\r
214 }\r
215 return NULL;\r
216 } else {\r
217 DEBUG ((EFI_D_INFO, "InitCommunicationContext - SmmConfigurationTable: %x\n", Smst->SmmConfigurationTable));\r
218 DEBUG ((EFI_D_INFO, "InitCommunicationContext - NumberOfTableEntries: %x\n", Smst->NumberOfTableEntries));\r
219 SmmConfigurationTable = Smst->SmmConfigurationTable;\r
220 NumberOfTableEntries = Smst->NumberOfTableEntries;\r
221 for (Index = 0; Index < NumberOfTableEntries; Index++) {\r
222 if (CompareGuid (&SmmConfigurationTable[Index].VendorGuid, VendorGuid)) {\r
223 return (VOID *)SmmConfigurationTable[Index].VendorTable;\r
224 }\r
225 }\r
226 return NULL;\r
227 }\r
228}\r
229\r
230/**\r
231 Init SMM communication context.\r
232**/\r
233VOID\r
234InitCommunicationContext (\r
235 VOID\r
236 )\r
237{\r
238 EFI_SMRAM_DESCRIPTOR *SmramDescriptor;\r
239 SMM_S3_RESUME_STATE *SmmS3ResumeState;\r
240 VOID *GuidHob;\r
241 EFI_SMM_COMMUNICATION_CONTEXT *SmmCommunicationContext;\r
242\r
243 GuidHob = GetFirstGuidHob (&gEfiAcpiVariableGuid);\r
244 ASSERT (GuidHob != NULL);\r
245 SmramDescriptor = (EFI_SMRAM_DESCRIPTOR *) GET_GUID_HOB_DATA (GuidHob);\r
246 SmmS3ResumeState = (SMM_S3_RESUME_STATE *)(UINTN)SmramDescriptor->CpuStart;\r
247\r
248 DEBUG ((EFI_D_INFO, "InitCommunicationContext - SmmS3ResumeState: %x\n", SmmS3ResumeState));\r
249 DEBUG ((EFI_D_INFO, "InitCommunicationContext - Smst: %x\n", SmmS3ResumeState->Smst));\r
250\r
251 SmmCommunicationContext = (EFI_SMM_COMMUNICATION_CONTEXT *)InternalSmstGetVendorTableByGuid (\r
252 SmmS3ResumeState->Signature,\r
253 (EFI_SMM_SYSTEM_TABLE2 *)(UINTN)SmmS3ResumeState->Smst,\r
254 &gEfiPeiSmmCommunicationPpiGuid\r
255 );\r
256 ASSERT (SmmCommunicationContext != NULL);\r
257\r
258 SetCommunicationContext (SmmCommunicationContext);\r
259\r
260 return ;\r
261}\r
262\r
263/**\r
264 Communicates with a registered handler.\r
265\r
266 This function provides a service to send and receive messages from a registered UEFI service.\r
267\r
268 @param[in] This The EFI_PEI_SMM_COMMUNICATION_PPI instance.\r
269 @param[in, out] CommBuffer A pointer to the buffer to convey into SMRAM.\r
270 @param[in, out] CommSize The size of the data buffer being passed in.On exit, the size of data\r
271 being returned. Zero if the handler does not wish to reply with any data.\r
272\r
273 @retval EFI_SUCCESS The message was successfully posted.\r
274 @retval EFI_INVALID_PARAMETER The CommBuffer was NULL.\r
275 @retval EFI_NOT_STARTED The service is NOT started.\r
276**/\r
277EFI_STATUS\r
278EFIAPI\r
279Communicate (\r
280 IN CONST EFI_PEI_SMM_COMMUNICATION_PPI *This,\r
281 IN OUT VOID *CommBuffer,\r
282 IN OUT UINTN *CommSize\r
283 )\r
284{\r
285 EFI_STATUS Status;\r
286 PEI_SMM_CONTROL_PPI *SmmControl;\r
287 PEI_SMM_ACCESS_PPI *SmmAccess;\r
288 UINT8 SmiCommand;\r
289 UINTN Size;\r
290 EFI_SMM_COMMUNICATION_CONTEXT *SmmCommunicationContext;\r
291\r
292 DEBUG ((EFI_D_INFO, "PiSmmCommunicationPei Communicate Enter\n"));\r
293\r
294 if (CommBuffer == NULL) {\r
295 return EFI_INVALID_PARAMETER;\r
296 }\r
297\r
298 //\r
299 // Get needed resource\r
300 //\r
301 Status = PeiServicesLocatePpi (\r
302 &gPeiSmmControlPpiGuid,\r
303 0,\r
304 NULL,\r
305 (VOID **)&SmmControl\r
306 );\r
307 if (EFI_ERROR (Status)) {\r
308 return EFI_NOT_STARTED;\r
309 }\r
310\r
311 Status = PeiServicesLocatePpi (\r
312 &gPeiSmmAccessPpiGuid,\r
313 0,\r
314 NULL,\r
315 (VOID **)&SmmAccess\r
316 );\r
317 if (EFI_ERROR (Status)) {\r
318 return EFI_NOT_STARTED;\r
319 }\r
320\r
321 //\r
322 // Check SMRAM locked, it should be done after SMRAM lock.\r
323 //\r
324 if (!SmmAccess->LockState) {\r
325 DEBUG ((EFI_D_INFO, "PiSmmCommunicationPei LockState - %x\n", (UINTN)SmmAccess->LockState));\r
326 return EFI_NOT_STARTED;\r
327 }\r
328\r
329 SmmCommunicationContext = GetCommunicationContext ();\r
330 DEBUG ((EFI_D_INFO, "PiSmmCommunicationPei BufferPtrAddress - 0x%016lx, BufferPtr: 0x%016lx\n", SmmCommunicationContext->BufferPtrAddress, *(EFI_PHYSICAL_ADDRESS *)(UINTN)SmmCommunicationContext->BufferPtrAddress));\r
331\r
332 //\r
333 // No need to check if BufferPtr is 0, because it is in PEI phase.\r
334 //\r
335 *(EFI_PHYSICAL_ADDRESS *)(UINTN)SmmCommunicationContext->BufferPtrAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)CommBuffer;\r
336 DEBUG ((EFI_D_INFO, "PiSmmCommunicationPei CommBuffer - %x\n", (UINTN)CommBuffer));\r
337\r
338 //\r
339 // Send command\r
340 //\r
341 SmiCommand = (UINT8)SmmCommunicationContext->SwSmiNumber;\r
342 Size = sizeof(SmiCommand);\r
343 Status = SmmControl->Trigger (\r
344 (EFI_PEI_SERVICES **)GetPeiServicesTablePointer (),\r
345 SmmControl,\r
346 (INT8 *)&SmiCommand,\r
347 &Size,\r
348 FALSE,\r
349 0\r
350 );\r
351 ASSERT_EFI_ERROR (Status);\r
352\r
353 //\r
354 // Setting BufferPtr to 0 means this transaction is done.\r
355 //\r
356 *(EFI_PHYSICAL_ADDRESS *)(UINTN)SmmCommunicationContext->BufferPtrAddress = 0;\r
357\r
358 DEBUG ((EFI_D_INFO, "PiSmmCommunicationPei Communicate Exit\n"));\r
359\r
360 return EFI_SUCCESS;\r
361}\r
362\r
363/**\r
364 Entry Point for PI SMM communication PEIM.\r
365\r
366 @param FileHandle Handle of the file being invoked.\r
367 @param PeiServices Pointer to PEI Services table.\r
368\r
369 @retval EFI_SUCEESS\r
370 @return Others Some error occurs.\r
371**/\r
372EFI_STATUS\r
373EFIAPI\r
374PiSmmCommunicationPeiEntryPoint (\r
375 IN EFI_PEI_FILE_HANDLE FileHandle,\r
376 IN CONST EFI_PEI_SERVICES **PeiServices\r
377 )\r
378{\r
379 EFI_STATUS Status;\r
380 PEI_SMM_ACCESS_PPI *SmmAccess;\r
381 EFI_BOOT_MODE BootMode;\r
382 UINTN Index;\r
383\r
384 BootMode = GetBootModeHob ();\r
385 if (BootMode != BOOT_ON_S3_RESUME) {\r
386 return EFI_UNSUPPORTED;\r
387 }\r
388\r
389 Status = PeiServicesLocatePpi (\r
390 &gPeiSmmAccessPpiGuid,\r
391 0,\r
392 NULL,\r
393 (VOID **)&SmmAccess\r
394 );\r
395 if (EFI_ERROR (Status)) {\r
396 return EFI_NOT_STARTED;\r
397 }\r
398\r
399 //\r
400 // Check SMRAM locked, it should be done before SMRAM lock.\r
401 //\r
402 if (SmmAccess->LockState) {\r
403 DEBUG ((EFI_D_INFO, "PiSmmCommunicationPei LockState - %x\n", (UINTN)SmmAccess->LockState));\r
404 return EFI_ACCESS_DENIED;\r
405 }\r
406\r
407 //\r
408 // Open all SMRAM\r
409 //\r
410 for (Index = 0; !EFI_ERROR (Status); Index++) {\r
411 Status = SmmAccess->Open ((EFI_PEI_SERVICES **)GetPeiServicesTablePointer (), SmmAccess, Index);\r
412 }\r
413\r
414 InitCommunicationContext ();\r
415\r
416 PeiServicesInstallPpi (&mPpiList);\r
417\r
418 return RETURN_SUCCESS;\r
419}\r