]> git.proxmox.com Git - mirror_edk2.git/blame - UefiCpuPkg/PiSmmCommunication/PiSmmCommunicationSmm.c
UefiCpuPkg: Add SMM Communication PPI and Handler Modules
[mirror_edk2.git] / UefiCpuPkg / PiSmmCommunication / PiSmmCommunicationSmm.c
CommitLineData
b3dc26ed
MK
1/** @file\r
2PiSmmCommunication SMM Driver.\r
3\r
4Copyright (c) 2010 - 2015, Intel Corporation. All rights reserved.<BR>\r
5This program and the accompanying materials\r
6are licensed and made available under the terms and conditions of the BSD License\r
7which accompanies this distribution. The full text of the license may be found at\r
8http://opensource.org/licenses/bsd-license.php\r
9\r
10THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
11WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
12\r
13**/\r
14\r
15#include <PiSmm.h>\r
16#include <Library/UefiDriverEntryPoint.h>\r
17#include <Library/UefiBootServicesTableLib.h>\r
18#include <Library/UefiRuntimeServicesTableLib.h>\r
19#include <Library/SmmServicesTableLib.h>\r
20#include <Library/BaseLib.h>\r
21#include <Library/BaseMemoryLib.h>\r
22#include <Library/HobLib.h>\r
23#include <Library/DebugLib.h>\r
24#include <Library/SmmMemLib.h>\r
25#include <Library/PcdLib.h>\r
26#include <Protocol/SmmSwDispatch2.h>\r
27#include <Protocol/SmmReadyToLock.h>\r
28#include <Protocol/SmmCommunication.h>\r
29#include <Protocol/AcpiTable.h>\r
30#include <Ppi/SmmCommunication.h>\r
31#include <Guid/Acpi.h>\r
32\r
33#include "PiSmmCommunicationPrivate.h"\r
34\r
35EFI_SMM_COMMUNICATION_CONTEXT mSmmCommunicationContext = {\r
36 SMM_COMMUNICATION_SIGNATURE\r
37};\r
38\r
39EFI_SMM_COMMUNICATION_ACPI_TABLE mSmmCommunicationAcpiTable = {\r
40 {\r
41 {\r
42 EFI_ACPI_4_0_UEFI_ACPI_DATA_TABLE_SIGNATURE,\r
43 sizeof (EFI_SMM_COMMUNICATION_ACPI_TABLE),\r
44 0x1, // Revision\r
45 0x0, // Checksum\r
46 {0x0}, // OemId[6]\r
47 0x0, // OemTableId\r
48 0x0, // OemRevision\r
49 0x0, // CreatorId\r
50 0x0 // CreatorRevision\r
51 },\r
52 {0x0}, // Identifier\r
53 OFFSET_OF (EFI_SMM_COMMUNICATION_ACPI_TABLE, SwSmiNumber) // DataOffset\r
54 },\r
55 0x0, // SwSmiNumber\r
56 0x0 // BufferPtrAddress\r
57};\r
58\r
59/**\r
60 Set SMM communication context.\r
61**/\r
62VOID\r
63SetCommunicationContext (\r
64 VOID\r
65 )\r
66{\r
67 EFI_STATUS Status;\r
68\r
69 Status = gSmst->SmmInstallConfigurationTable (\r
70 gSmst,\r
71 &gEfiPeiSmmCommunicationPpiGuid,\r
72 &mSmmCommunicationContext,\r
73 sizeof(mSmmCommunicationContext)\r
74 );\r
75 ASSERT_EFI_ERROR (Status);\r
76}\r
77\r
78/**\r
79 Dispatch function for a Software SMI handler.\r
80\r
81 @param DispatchHandle The unique handle assigned to this handler by SmiHandlerRegister().\r
82 @param Context Points to an optional handler context which was specified when the\r
83 handler was registered.\r
84 @param CommBuffer A pointer to a collection of data in memory that will\r
85 be conveyed from a non-SMM environment into an SMM environment.\r
86 @param CommBufferSize The size of the CommBuffer.\r
87\r
88 @retval EFI_SUCCESS Command is handled successfully.\r
89\r
90**/\r
91EFI_STATUS\r
92EFIAPI\r
93PiSmmCommunicationHandler (\r
94 IN EFI_HANDLE DispatchHandle,\r
95 IN CONST VOID *Context OPTIONAL,\r
96 IN OUT VOID *CommBuffer OPTIONAL,\r
97 IN OUT UINTN *CommBufferSize OPTIONAL\r
98 )\r
99{\r
100 UINTN CommSize;\r
101 EFI_STATUS Status;\r
102 EFI_SMM_COMMUNICATE_HEADER *CommunicateHeader;\r
103 EFI_PHYSICAL_ADDRESS *BufferPtrAddress;\r
104\r
105 DEBUG ((EFI_D_INFO, "PiSmmCommunicationHandler Enter\n"));\r
106\r
107 BufferPtrAddress = (EFI_PHYSICAL_ADDRESS *)(UINTN)mSmmCommunicationContext.BufferPtrAddress;\r
108 CommunicateHeader = (EFI_SMM_COMMUNICATE_HEADER *)(UINTN)*BufferPtrAddress;\r
109 DEBUG ((EFI_D_INFO, "PiSmmCommunicationHandler CommunicateHeader - %x\n", CommunicateHeader));\r
110 if (CommunicateHeader == NULL) {\r
111 DEBUG ((EFI_D_INFO, "PiSmmCommunicationHandler is NULL, needn't to call dispatch function\n"));\r
112 Status = EFI_SUCCESS;\r
113 } else {\r
114 if (!SmmIsBufferOutsideSmmValid ((UINTN)CommunicateHeader, OFFSET_OF (EFI_SMM_COMMUNICATE_HEADER, Data))) {\r
115 DEBUG ((EFI_D_INFO, "PiSmmCommunicationHandler CommunicateHeader invalid - 0x%x\n", CommunicateHeader));\r
116 Status = EFI_SUCCESS;\r
117 goto Done;\r
118 }\r
119\r
120 CommSize = (UINTN)CommunicateHeader->MessageLength;\r
121 if (!SmmIsBufferOutsideSmmValid ((UINTN)&CommunicateHeader->Data[0], CommSize)) {\r
122 DEBUG ((EFI_D_INFO, "PiSmmCommunicationHandler CommunicateData invalid - 0x%x\n", &CommunicateHeader->Data[0]));\r
123 Status = EFI_SUCCESS;\r
124 goto Done;\r
125 }\r
126\r
127 //\r
128 // Call dispatch function\r
129 //\r
130 DEBUG ((EFI_D_INFO, "PiSmmCommunicationHandler Data - %x\n", &CommunicateHeader->Data[0]));\r
131 Status = gSmst->SmiManage (\r
132 &CommunicateHeader->HeaderGuid,\r
133 NULL,\r
134 &CommunicateHeader->Data[0],\r
135 &CommSize\r
136 );\r
137 }\r
138\r
139Done:\r
140 DEBUG ((EFI_D_INFO, "PiSmmCommunicationHandler %r\n", Status));\r
141 DEBUG ((EFI_D_INFO, "PiSmmCommunicationHandler Exit\n"));\r
142\r
143 return (Status == EFI_SUCCESS) ? EFI_SUCCESS : EFI_INTERRUPT_PENDING;\r
144}\r
145\r
146/**\r
147 Allocate EfiACPIMemoryNVS below 4G memory address.\r
148\r
149 This function allocates EfiACPIMemoryNVS below 4G memory address.\r
150\r
151 @param Size Size of memory to allocate.\r
152\r
153 @return Allocated address for output.\r
154\r
155**/\r
156VOID*\r
157AllocateAcpiNvsMemoryBelow4G (\r
158 IN UINTN Size\r
159 )\r
160{\r
161 UINTN Pages;\r
162 EFI_PHYSICAL_ADDRESS Address;\r
163 EFI_STATUS Status;\r
164 VOID* Buffer;\r
165\r
166 Pages = EFI_SIZE_TO_PAGES (Size);\r
167 Address = 0xffffffff;\r
168\r
169 Status = gBS->AllocatePages (\r
170 AllocateMaxAddress,\r
171 EfiACPIMemoryNVS,\r
172 Pages,\r
173 &Address\r
174 );\r
175 ASSERT_EFI_ERROR (Status);\r
176\r
177 Buffer = (VOID *) (UINTN) Address;\r
178 ZeroMem (Buffer, Size);\r
179\r
180 return Buffer;\r
181}\r
182\r
183/**\r
184 Entry Point for PI SMM communication SMM driver.\r
185\r
186 @param[in] ImageHandle Image handle of this driver.\r
187 @param[in] SystemTable A Pointer to the EFI System Table.\r
188\r
189 @retval EFI_SUCEESS\r
190 @return Others Some error occurs.\r
191**/\r
192EFI_STATUS\r
193EFIAPI\r
194PiSmmCommunicationSmmEntryPoint (\r
195 IN EFI_HANDLE ImageHandle,\r
196 IN EFI_SYSTEM_TABLE *SystemTable\r
197 )\r
198{\r
199 EFI_STATUS Status;\r
200 EFI_SMM_SW_DISPATCH2_PROTOCOL *SmmSwDispatch2;\r
201 EFI_SMM_SW_REGISTER_CONTEXT SmmSwDispatchContext;\r
202 EFI_HANDLE DispatchHandle;\r
203 EFI_ACPI_TABLE_PROTOCOL *AcpiTableProtocol;\r
204 UINTN TableKey;\r
205 UINT64 OemTableId;\r
206 EFI_PHYSICAL_ADDRESS *BufferPtrAddress;\r
207\r
208 CopyMem (\r
209 mSmmCommunicationAcpiTable.UefiAcpiDataTable.Header.OemId,\r
210 PcdGetPtr (PcdAcpiDefaultOemId),\r
211 sizeof (mSmmCommunicationAcpiTable.UefiAcpiDataTable.Header.OemId)\r
212 );\r
213 OemTableId = PcdGet64 (PcdAcpiDefaultOemTableId);\r
214 CopyMem (&mSmmCommunicationAcpiTable.UefiAcpiDataTable.Header.OemTableId, &OemTableId, sizeof (UINT64));\r
215 mSmmCommunicationAcpiTable.UefiAcpiDataTable.Header.OemRevision = PcdGet32 (PcdAcpiDefaultOemRevision);\r
216 mSmmCommunicationAcpiTable.UefiAcpiDataTable.Header.CreatorId = PcdGet32 (PcdAcpiDefaultCreatorId);\r
217 mSmmCommunicationAcpiTable.UefiAcpiDataTable.Header.CreatorRevision = PcdGet32 (PcdAcpiDefaultCreatorRevision);\r
218\r
219 //\r
220 // Register software SMI handler\r
221 //\r
222 Status = gSmst->SmmLocateProtocol (\r
223 &gEfiSmmSwDispatch2ProtocolGuid,\r
224 NULL,\r
225 (VOID **)&SmmSwDispatch2\r
226 );\r
227 ASSERT_EFI_ERROR (Status);\r
228\r
229 SmmSwDispatchContext.SwSmiInputValue = (UINTN)-1;\r
230 Status = SmmSwDispatch2->Register (\r
231 SmmSwDispatch2,\r
232 PiSmmCommunicationHandler,\r
233 &SmmSwDispatchContext,\r
234 &DispatchHandle\r
235 );\r
236 ASSERT_EFI_ERROR (Status);\r
237\r
238 DEBUG ((EFI_D_INFO, "SmmCommunication SwSmi: %x\n", (UINTN)SmmSwDispatchContext.SwSmiInputValue));\r
239\r
240 //\r
241 // Set ACPI table\r
242 //\r
243 Status = gBS->LocateProtocol (&gEfiAcpiTableProtocolGuid, NULL, (VOID **) &AcpiTableProtocol);\r
244 ASSERT_EFI_ERROR (Status);\r
245\r
246 mSmmCommunicationAcpiTable.SwSmiNumber = (UINT32)SmmSwDispatchContext.SwSmiInputValue;\r
247 BufferPtrAddress = AllocateAcpiNvsMemoryBelow4G (sizeof(EFI_PHYSICAL_ADDRESS));\r
248 ASSERT (BufferPtrAddress != NULL);\r
249 DEBUG ((EFI_D_INFO, "SmmCommunication BufferPtrAddress: 0x%016lx, BufferPtr: 0x%016lx\n", (EFI_PHYSICAL_ADDRESS)(UINTN)BufferPtrAddress, *BufferPtrAddress));\r
250 mSmmCommunicationAcpiTable.BufferPtrAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)BufferPtrAddress;\r
251 CopyMem (&mSmmCommunicationAcpiTable.UefiAcpiDataTable.Identifier, &gEfiSmmCommunicationProtocolGuid, sizeof(gEfiSmmCommunicationProtocolGuid));\r
252\r
253 Status = AcpiTableProtocol->InstallAcpiTable (\r
254 AcpiTableProtocol,\r
255 &mSmmCommunicationAcpiTable,\r
256 sizeof(mSmmCommunicationAcpiTable),\r
257 &TableKey\r
258 );\r
259 ASSERT_EFI_ERROR (Status);\r
260\r
261 //\r
262 // Save context\r
263 //\r
264 mSmmCommunicationContext.SwSmiNumber = (UINT32)SmmSwDispatchContext.SwSmiInputValue;\r
265 mSmmCommunicationContext.BufferPtrAddress = mSmmCommunicationAcpiTable.BufferPtrAddress;\r
266 SetCommunicationContext ();\r
267\r
268 return Status;\r
269}\r