]> git.proxmox.com Git - mirror_edk2.git/blame - UefiCpuPkg/PiSmmCommunication/PiSmmCommunicationPei.c
UefiCpuPkg/SmmCommunication: Remove out-dated comments
[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
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 ((EFI_D_INFO, "InitCommunicationContext - SmmConfigurationTable: %x\n", Smst64->SmmConfigurationTable));\r
201 DEBUG ((EFI_D_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 return NULL;\r
210 } else {\r
211 DEBUG ((EFI_D_INFO, "InitCommunicationContext - SmmConfigurationTable: %x\n", Smst->SmmConfigurationTable));\r
212 DEBUG ((EFI_D_INFO, "InitCommunicationContext - NumberOfTableEntries: %x\n", Smst->NumberOfTableEntries));\r
213 SmmConfigurationTable = Smst->SmmConfigurationTable;\r
214 NumberOfTableEntries = Smst->NumberOfTableEntries;\r
215 for (Index = 0; Index < NumberOfTableEntries; Index++) {\r
216 if (CompareGuid (&SmmConfigurationTable[Index].VendorGuid, VendorGuid)) {\r
217 return (VOID *)SmmConfigurationTable[Index].VendorTable;\r
218 }\r
219 }\r
220 return NULL;\r
221 }\r
222}\r
223\r
224/**\r
225 Init SMM communication context.\r
226**/\r
227VOID\r
228InitCommunicationContext (\r
229 VOID\r
230 )\r
231{\r
232 EFI_SMRAM_DESCRIPTOR *SmramDescriptor;\r
233 SMM_S3_RESUME_STATE *SmmS3ResumeState;\r
234 VOID *GuidHob;\r
235 EFI_SMM_COMMUNICATION_CONTEXT *SmmCommunicationContext;\r
236\r
237 GuidHob = GetFirstGuidHob (&gEfiAcpiVariableGuid);\r
238 ASSERT (GuidHob != NULL);\r
239 SmramDescriptor = (EFI_SMRAM_DESCRIPTOR *) GET_GUID_HOB_DATA (GuidHob);\r
240 SmmS3ResumeState = (SMM_S3_RESUME_STATE *)(UINTN)SmramDescriptor->CpuStart;\r
241\r
242 DEBUG ((EFI_D_INFO, "InitCommunicationContext - SmmS3ResumeState: %x\n", SmmS3ResumeState));\r
243 DEBUG ((EFI_D_INFO, "InitCommunicationContext - Smst: %x\n", SmmS3ResumeState->Smst));\r
244\r
245 SmmCommunicationContext = (EFI_SMM_COMMUNICATION_CONTEXT *)InternalSmstGetVendorTableByGuid (\r
246 SmmS3ResumeState->Signature,\r
247 (EFI_SMM_SYSTEM_TABLE2 *)(UINTN)SmmS3ResumeState->Smst,\r
248 &gEfiPeiSmmCommunicationPpiGuid\r
249 );\r
250 ASSERT (SmmCommunicationContext != NULL);\r
251\r
252 SetCommunicationContext (SmmCommunicationContext);\r
253\r
254 return ;\r
255}\r
256\r
257/**\r
258 Communicates with a registered handler.\r
259\r
260 This function provides a service to send and receive messages from a registered UEFI service.\r
261\r
262 @param[in] This The EFI_PEI_SMM_COMMUNICATION_PPI instance.\r
263 @param[in, out] CommBuffer A pointer to the buffer to convey into SMRAM.\r
264 @param[in, out] CommSize The size of the data buffer being passed in.On exit, the size of data\r
265 being returned. Zero if the handler does not wish to reply with any data.\r
266\r
267 @retval EFI_SUCCESS The message was successfully posted.\r
268 @retval EFI_INVALID_PARAMETER The CommBuffer was NULL.\r
269 @retval EFI_NOT_STARTED The service is NOT started.\r
270**/\r
271EFI_STATUS\r
272EFIAPI\r
273Communicate (\r
274 IN CONST EFI_PEI_SMM_COMMUNICATION_PPI *This,\r
275 IN OUT VOID *CommBuffer,\r
276 IN OUT UINTN *CommSize\r
277 )\r
278{\r
279 EFI_STATUS Status;\r
280 PEI_SMM_CONTROL_PPI *SmmControl;\r
281 PEI_SMM_ACCESS_PPI *SmmAccess;\r
282 UINT8 SmiCommand;\r
283 UINTN Size;\r
284 EFI_SMM_COMMUNICATION_CONTEXT *SmmCommunicationContext;\r
285\r
286 DEBUG ((EFI_D_INFO, "PiSmmCommunicationPei Communicate Enter\n"));\r
287\r
288 if (CommBuffer == NULL) {\r
289 return EFI_INVALID_PARAMETER;\r
290 }\r
291\r
292 //\r
293 // Get needed resource\r
294 //\r
295 Status = PeiServicesLocatePpi (\r
296 &gPeiSmmControlPpiGuid,\r
297 0,\r
298 NULL,\r
299 (VOID **)&SmmControl\r
300 );\r
301 if (EFI_ERROR (Status)) {\r
302 return EFI_NOT_STARTED;\r
303 }\r
304\r
305 Status = PeiServicesLocatePpi (\r
306 &gPeiSmmAccessPpiGuid,\r
307 0,\r
308 NULL,\r
309 (VOID **)&SmmAccess\r
310 );\r
311 if (EFI_ERROR (Status)) {\r
312 return EFI_NOT_STARTED;\r
313 }\r
314\r
315 //\r
316 // Check SMRAM locked, it should be done after SMRAM lock.\r
317 //\r
318 if (!SmmAccess->LockState) {\r
319 DEBUG ((EFI_D_INFO, "PiSmmCommunicationPei LockState - %x\n", (UINTN)SmmAccess->LockState));\r
320 return EFI_NOT_STARTED;\r
321 }\r
322\r
323 SmmCommunicationContext = GetCommunicationContext ();\r
324 DEBUG ((EFI_D_INFO, "PiSmmCommunicationPei BufferPtrAddress - 0x%016lx, BufferPtr: 0x%016lx\n", SmmCommunicationContext->BufferPtrAddress, *(EFI_PHYSICAL_ADDRESS *)(UINTN)SmmCommunicationContext->BufferPtrAddress));\r
325\r
326 //\r
327 // No need to check if BufferPtr is 0, because it is in PEI phase.\r
328 //\r
329 *(EFI_PHYSICAL_ADDRESS *)(UINTN)SmmCommunicationContext->BufferPtrAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)CommBuffer;\r
330 DEBUG ((EFI_D_INFO, "PiSmmCommunicationPei CommBuffer - %x\n", (UINTN)CommBuffer));\r
331\r
332 //\r
333 // Send command\r
334 //\r
335 SmiCommand = (UINT8)SmmCommunicationContext->SwSmiNumber;\r
336 Size = sizeof(SmiCommand);\r
337 Status = SmmControl->Trigger (\r
338 (EFI_PEI_SERVICES **)GetPeiServicesTablePointer (),\r
339 SmmControl,\r
340 (INT8 *)&SmiCommand,\r
341 &Size,\r
342 FALSE,\r
343 0\r
344 );\r
345 ASSERT_EFI_ERROR (Status);\r
346\r
347 //\r
348 // Setting BufferPtr to 0 means this transaction is done.\r
349 //\r
350 *(EFI_PHYSICAL_ADDRESS *)(UINTN)SmmCommunicationContext->BufferPtrAddress = 0;\r
351\r
352 DEBUG ((EFI_D_INFO, "PiSmmCommunicationPei Communicate Exit\n"));\r
353\r
354 return EFI_SUCCESS;\r
355}\r
356\r
357/**\r
358 Entry Point for PI SMM communication PEIM.\r
359\r
360 @param FileHandle Handle of the file being invoked.\r
361 @param PeiServices Pointer to PEI Services table.\r
362\r
ef62da4f 363 @retval EFI_SUCCESS\r
b3dc26ed
MK
364 @return Others Some error occurs.\r
365**/\r
366EFI_STATUS\r
367EFIAPI\r
368PiSmmCommunicationPeiEntryPoint (\r
369 IN EFI_PEI_FILE_HANDLE FileHandle,\r
370 IN CONST EFI_PEI_SERVICES **PeiServices\r
371 )\r
372{\r
373 EFI_STATUS Status;\r
374 PEI_SMM_ACCESS_PPI *SmmAccess;\r
375 EFI_BOOT_MODE BootMode;\r
376 UINTN Index;\r
377\r
378 BootMode = GetBootModeHob ();\r
379 if (BootMode != BOOT_ON_S3_RESUME) {\r
380 return EFI_UNSUPPORTED;\r
381 }\r
382\r
383 Status = PeiServicesLocatePpi (\r
384 &gPeiSmmAccessPpiGuid,\r
385 0,\r
386 NULL,\r
387 (VOID **)&SmmAccess\r
388 );\r
389 if (EFI_ERROR (Status)) {\r
390 return EFI_NOT_STARTED;\r
391 }\r
392\r
393 //\r
394 // Check SMRAM locked, it should be done before SMRAM lock.\r
395 //\r
396 if (SmmAccess->LockState) {\r
397 DEBUG ((EFI_D_INFO, "PiSmmCommunicationPei LockState - %x\n", (UINTN)SmmAccess->LockState));\r
398 return EFI_ACCESS_DENIED;\r
399 }\r
400\r
401 //\r
402 // Open all SMRAM\r
403 //\r
404 for (Index = 0; !EFI_ERROR (Status); Index++) {\r
405 Status = SmmAccess->Open ((EFI_PEI_SERVICES **)GetPeiServicesTablePointer (), SmmAccess, Index);\r
406 }\r
407\r
408 InitCommunicationContext ();\r
409\r
410 PeiServicesInstallPpi (&mPpiList);\r
411\r
412 return RETURN_SUCCESS;\r
413}\r