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