]> git.proxmox.com Git - mirror_edk2.git/blame - UefiCpuPkg/PiSmmCommunication/PiSmmCommunicationPei.c
UefiCpuPkg: Apply uncrustify changes
[mirror_edk2.git] / UefiCpuPkg / PiSmmCommunication / PiSmmCommunicationPei.c
CommitLineData
b3dc26ed
MK
1/** @file\r
2PiSmmCommunication PEI Driver.\r
3\r
30691a4b 4Copyright (c) 2010 - 2021, 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
30691a4b
RN
50 | BufferPtrAddress |---\r
51 +----------------------------------+ |\r
52 |\r
53 +----------------------------------+<--\r
b3dc26ed
MK
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
053e878b
MK
89 EFI_GUID VendorGuid;\r
90 UINT64 VendorTable;\r
b3dc26ed
MK
91} EFI_CONFIGURATION_TABLE64;\r
92#endif\r
93\r
94#if defined (MDE_CPU_X64)\r
053e878b
MK
95typedef EFI_SMM_SYSTEM_TABLE2 EFI_SMM_SYSTEM_TABLE2_64;\r
96typedef EFI_CONFIGURATION_TABLE EFI_CONFIGURATION_TABLE64;\r
b3dc26ed
MK
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
053e878b
MK
116 IN CONST EFI_PEI_SMM_COMMUNICATION_PPI *This,\r
117 IN OUT VOID *CommBuffer,\r
118 IN OUT UINTN *CommSize\r
b3dc26ed
MK
119 );\r
120\r
053e878b 121EFI_PEI_SMM_COMMUNICATION_PPI mSmmCommunicationPpi = { Communicate };\r
b3dc26ed 122\r
053e878b 123EFI_PEI_PPI_DESCRIPTOR mPpiList = {\r
b3dc26ed
MK
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
053e878b
MK
139 EFI_HOB_GUID_TYPE *GuidHob;\r
140 EFI_SMM_COMMUNICATION_CONTEXT *SmmCommunicationContext;\r
b3dc26ed
MK
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
053e878b 157 IN EFI_SMM_COMMUNICATION_CONTEXT *SmmCommunicationContext\r
b3dc26ed
MK
158 )\r
159{\r
053e878b
MK
160 EFI_PEI_HOB_POINTERS Hob;\r
161 UINTN BufferSize;\r
b3dc26ed
MK
162\r
163 BufferSize = sizeof (*SmmCommunicationContext);\r
053e878b
MK
164 Hob.Raw = BuildGuidHob (\r
165 &gEfiPeiSmmCommunicationPpiGuid,\r
166 BufferSize\r
167 );\r
b3dc26ed
MK
168 ASSERT (Hob.Raw);\r
169\r
053e878b 170 CopyMem ((VOID *)Hob.Raw, SmmCommunicationContext, sizeof (*SmmCommunicationContext));\r
b3dc26ed
MK
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
053e878b
MK
184 IN UINT64 Signature,\r
185 IN EFI_SMM_SYSTEM_TABLE2 *Smst,\r
186 IN EFI_GUID *VendorGuid\r
b3dc26ed
MK
187 )\r
188{\r
053e878b
MK
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
b3dc26ed 194\r
053e878b 195 if ((sizeof (UINTN) == sizeof (UINT32)) && (Signature == SMM_S3_RESUME_SMM_64)) {\r
b3dc26ed
MK
196 //\r
197 // 32 PEI + 64 DXE\r
198 //\r
199 Smst64 = (EFI_SMM_SYSTEM_TABLE2_64 *)Smst;\r
96e1cba5
MK
200 DEBUG ((DEBUG_INFO, "InitCommunicationContext - SmmConfigurationTable: %x\n", Smst64->SmmConfigurationTable));\r
201 DEBUG ((DEBUG_INFO, "InitCommunicationContext - NumberOfTableEntries: %x\n", Smst64->NumberOfTableEntries));\r
b3dc26ed 202 SmmConfigurationTable64 = (EFI_CONFIGURATION_TABLE64 *)(UINTN)Smst64->SmmConfigurationTable;\r
053e878b 203 NumberOfTableEntries = (UINTN)Smst64->NumberOfTableEntries;\r
b3dc26ed
MK
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
053e878b 209\r
b3dc26ed
MK
210 return NULL;\r
211 } else {\r
96e1cba5
MK
212 DEBUG ((DEBUG_INFO, "InitCommunicationContext - SmmConfigurationTable: %x\n", Smst->SmmConfigurationTable));\r
213 DEBUG ((DEBUG_INFO, "InitCommunicationContext - NumberOfTableEntries: %x\n", Smst->NumberOfTableEntries));\r
b3dc26ed 214 SmmConfigurationTable = Smst->SmmConfigurationTable;\r
053e878b 215 NumberOfTableEntries = Smst->NumberOfTableEntries;\r
b3dc26ed
MK
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
053e878b 221\r
b3dc26ed
MK
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
053e878b
MK
234 EFI_SMRAM_DESCRIPTOR *SmramDescriptor;\r
235 SMM_S3_RESUME_STATE *SmmS3ResumeState;\r
236 VOID *GuidHob;\r
237 EFI_SMM_COMMUNICATION_CONTEXT *SmmCommunicationContext;\r
b3dc26ed
MK
238\r
239 GuidHob = GetFirstGuidHob (&gEfiAcpiVariableGuid);\r
240 ASSERT (GuidHob != NULL);\r
053e878b 241 SmramDescriptor = (EFI_SMRAM_DESCRIPTOR *)GET_GUID_HOB_DATA (GuidHob);\r
b3dc26ed
MK
242 SmmS3ResumeState = (SMM_S3_RESUME_STATE *)(UINTN)SmramDescriptor->CpuStart;\r
243\r
96e1cba5
MK
244 DEBUG ((DEBUG_INFO, "InitCommunicationContext - SmmS3ResumeState: %x\n", SmmS3ResumeState));\r
245 DEBUG ((DEBUG_INFO, "InitCommunicationContext - Smst: %x\n", SmmS3ResumeState->Smst));\r
b3dc26ed
MK
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
053e878b 256 return;\r
b3dc26ed
MK
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
053e878b
MK
276 IN CONST EFI_PEI_SMM_COMMUNICATION_PPI *This,\r
277 IN OUT VOID *CommBuffer,\r
278 IN OUT UINTN *CommSize\r
b3dc26ed
MK
279 )\r
280{\r
053e878b
MK
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
b3dc26ed 287\r
96e1cba5 288 DEBUG ((DEBUG_INFO, "PiSmmCommunicationPei Communicate Enter\n"));\r
b3dc26ed
MK
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
96e1cba5 321 DEBUG ((DEBUG_INFO, "PiSmmCommunicationPei LockState - %x\n", (UINTN)SmmAccess->LockState));\r
b3dc26ed
MK
322 return EFI_NOT_STARTED;\r
323 }\r
324\r
325 SmmCommunicationContext = GetCommunicationContext ();\r
96e1cba5 326 DEBUG ((DEBUG_INFO, "PiSmmCommunicationPei BufferPtrAddress - 0x%016lx, BufferPtr: 0x%016lx\n", SmmCommunicationContext->BufferPtrAddress, *(EFI_PHYSICAL_ADDRESS *)(UINTN)SmmCommunicationContext->BufferPtrAddress));\r
b3dc26ed
MK
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
96e1cba5 332 DEBUG ((DEBUG_INFO, "PiSmmCommunicationPei CommBuffer - %x\n", (UINTN)CommBuffer));\r
b3dc26ed
MK
333\r
334 //\r
335 // Send command\r
336 //\r
337 SmiCommand = (UINT8)SmmCommunicationContext->SwSmiNumber;\r
053e878b
MK
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
b3dc26ed
MK
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
96e1cba5 354 DEBUG ((DEBUG_INFO, "PiSmmCommunicationPei Communicate Exit\n"));\r
b3dc26ed
MK
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
ef62da4f 365 @retval EFI_SUCCESS\r
b3dc26ed
MK
366 @return Others Some error occurs.\r
367**/\r
368EFI_STATUS\r
369EFIAPI\r
370PiSmmCommunicationPeiEntryPoint (\r
053e878b
MK
371 IN EFI_PEI_FILE_HANDLE FileHandle,\r
372 IN CONST EFI_PEI_SERVICES **PeiServices\r
b3dc26ed
MK
373 )\r
374{\r
053e878b
MK
375 EFI_STATUS Status;\r
376 PEI_SMM_ACCESS_PPI *SmmAccess;\r
377 EFI_BOOT_MODE BootMode;\r
378 UINTN Index;\r
b3dc26ed
MK
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
96e1cba5 399 DEBUG ((DEBUG_INFO, "PiSmmCommunicationPei LockState - %x\n", (UINTN)SmmAccess->LockState));\r
b3dc26ed
MK
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