]> git.proxmox.com Git - mirror_edk2.git/blame - QuarkSocPkg/QuarkNorthCluster/Smm/Pei/SmmAccessPei/SmmAccessPei.c
QuarkSocPkg: Add new package for Quark SoC X1000
[mirror_edk2.git] / QuarkSocPkg / QuarkNorthCluster / Smm / Pei / SmmAccessPei / SmmAccessPei.c
CommitLineData
9b6bbcdb
MK
1/** @file\r
2This is the driver that publishes the SMM Access Ppi\r
3instance for the Quark SOC.\r
4\r
5Copyright (c) 2013-2015 Intel Corporation.\r
6\r
7This program and the accompanying materials\r
8are licensed and made available under the terms and conditions of the BSD License\r
9which accompanies this distribution. The full text of the license may be found at\r
10http://opensource.org/licenses/bsd-license.php\r
11\r
12THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
13WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
14\r
15**/\r
16#include <PiPei.h>\r
17#include <Ppi/SmmAccess.h>\r
18#include <Guid/SmramMemoryReserve.h>\r
19#include <Library/BaseMemoryLib.h>\r
20#include <Library/MemoryAllocationLib.h>\r
21#include <Library/DebugLib.h>\r
22#include <Library/HobLib.h>\r
23#include <Library/PciLib.h>\r
24#include <Library/PeiServicesLib.h>\r
25#include <Library/QNCSmmLib.h>\r
26#include <QNCAccess.h>\r
27\r
28#define SMM_ACCESS_PRIVATE_DATA_FROM_THIS(a) \\r
29 CR ( \\r
30 a, \\r
31 SMM_ACCESS_PRIVATE_DATA, \\r
32 SmmAccess, \\r
33 SMM_ACCESS_PRIVATE_DATA_SIGNATURE \\r
34 )\r
35\r
36#define MAX_CPU_SOCKET 1\r
37#define MAX_SMRAM_RANGES 4\r
38\r
39typedef struct {\r
40 UINTN Signature;\r
41 EFI_HANDLE Handle;\r
42 PEI_SMM_ACCESS_PPI SmmAccess;\r
43 UINTN NumberRegions;\r
44 EFI_SMRAM_DESCRIPTOR SmramDesc[MAX_SMRAM_RANGES];\r
45 UINT8 TsegSize;\r
46 UINT8 MaxBusNumber;\r
47 UINT8 SocketPopulated[MAX_CPU_SOCKET];\r
48 UINT8 SocketBusNum[MAX_CPU_SOCKET];\r
49} SMM_ACCESS_PRIVATE_DATA;\r
50\r
51#define SMM_ACCESS_PRIVATE_DATA_SIGNATURE SIGNATURE_32 ('i', 's', 'm', 'a')\r
52\r
53\r
54EFI_STATUS\r
55EFIAPI\r
56Open (\r
57 IN EFI_PEI_SERVICES **PeiServices,\r
58 IN PEI_SMM_ACCESS_PPI *This,\r
59 IN UINTN DescriptorIndex\r
60 )\r
61/*++\r
62\r
63Routine Description:\r
64\r
65 This routine accepts a request to "open" a region of SMRAM. The\r
66 region could be legacy ABSEG, HSEG, or TSEG near top of physical memory.\r
67 The use of "open" means that the memory is visible from all PEIM\r
68 and SMM agents.\r
69\r
70Arguments:\r
71\r
72 PeiServices - General purpose services available to every PEIM.\r
73 This - Pointer to the SMM Access Interface.\r
74 DescriptorIndex - Region of SMRAM to Open.\r
75\r
76Returns:\r
77\r
78 EFI_SUCCESS - The region was successfully opened.\r
79 EFI_DEVICE_ERROR - The region could not be opened because locked by\r
80 chipset.\r
81 EFI_INVALID_PARAMETER - The descriptor index was out of bounds.\r
82\r
83--*/\r
84{\r
85 SMM_ACCESS_PRIVATE_DATA *SmmAccess;\r
86\r
87 SmmAccess = SMM_ACCESS_PRIVATE_DATA_FROM_THIS (This);\r
88\r
89 if (DescriptorIndex >= SmmAccess->NumberRegions) {\r
90 return EFI_INVALID_PARAMETER;\r
91 } else if (SmmAccess->SmramDesc[DescriptorIndex].RegionState & EFI_SMRAM_LOCKED) {\r
92 return EFI_DEVICE_ERROR;\r
93 }\r
94\r
95 //\r
96 // Open TSEG\r
97 //\r
98 if (!QNCOpenSmramRegion ()) {\r
99 SmmAccess->SmramDesc[DescriptorIndex].RegionState |= EFI_SMRAM_LOCKED;\r
100 return EFI_DEVICE_ERROR;\r
101 }\r
102\r
103 SmmAccess->SmramDesc[DescriptorIndex].RegionState &= ~(EFI_SMRAM_CLOSED | EFI_ALLOCATED);\r
104 SmmAccess->SmramDesc[DescriptorIndex].RegionState |= EFI_SMRAM_OPEN;\r
105 SmmAccess->SmmAccess.OpenState = TRUE;\r
106\r
107 return EFI_SUCCESS;\r
108}\r
109\r
110EFI_STATUS\r
111EFIAPI\r
112Close (\r
113 IN EFI_PEI_SERVICES **PeiServices,\r
114 IN PEI_SMM_ACCESS_PPI *This,\r
115 IN UINTN DescriptorIndex\r
116 )\r
117/*++\r
118\r
119Routine Description:\r
120\r
121 This routine accepts a request to "close" a region of SMRAM. This is valid for\r
122 compatible SMRAM region.\r
123\r
124Arguments:\r
125\r
126 PeiServices - General purpose services available to every PEIM.\r
127 This - Pointer to the SMM Access Interface.\r
128 DescriptorIndex - Region of SMRAM to Close.\r
129\r
130Returns:\r
131\r
132 EFI_SUCCESS - The region was successfully closed.\r
133 EFI_DEVICE_ERROR - The region could not be closed because locked by\r
134 chipset.\r
135 EFI_INVALID_PARAMETER - The descriptor index was out of bounds.\r
136\r
137--*/\r
138{\r
139 SMM_ACCESS_PRIVATE_DATA *SmmAccess;\r
140 BOOLEAN OpenState;\r
141 UINTN Index;\r
142\r
143\r
144 SmmAccess = SMM_ACCESS_PRIVATE_DATA_FROM_THIS (This);\r
145\r
146 if (DescriptorIndex >= SmmAccess->NumberRegions) {\r
147 return EFI_INVALID_PARAMETER;\r
148 } else if (SmmAccess->SmramDesc[DescriptorIndex].RegionState & EFI_SMRAM_LOCKED) {\r
149 return EFI_DEVICE_ERROR;\r
150 }\r
151\r
152 if (SmmAccess->SmramDesc[DescriptorIndex].RegionState & EFI_SMRAM_CLOSED) {\r
153 return EFI_DEVICE_ERROR;\r
154 }\r
155\r
156 //\r
157 // Close TSEG\r
158 //\r
159 if (!QNCCloseSmramRegion ()) {\r
160 SmmAccess->SmramDesc[DescriptorIndex].RegionState |= EFI_SMRAM_LOCKED;\r
161 return EFI_DEVICE_ERROR;\r
162 }\r
163\r
164 SmmAccess->SmramDesc[DescriptorIndex].RegionState &= ~EFI_SMRAM_OPEN;\r
165 SmmAccess->SmramDesc[DescriptorIndex].RegionState |= (EFI_SMRAM_CLOSED | EFI_ALLOCATED);\r
166\r
167 //\r
168 // Find out if any regions are still open\r
169 //\r
170 OpenState = FALSE;\r
171 for (Index = 0; Index < SmmAccess->NumberRegions; Index++) {\r
172 if ((SmmAccess->SmramDesc[Index].RegionState & EFI_SMRAM_OPEN) == EFI_SMRAM_OPEN) {\r
173 OpenState = TRUE;\r
174 }\r
175 }\r
176\r
177 SmmAccess->SmmAccess.OpenState = OpenState;\r
178\r
179 return EFI_SUCCESS;\r
180}\r
181\r
182EFI_STATUS\r
183EFIAPI\r
184Lock (\r
185 IN EFI_PEI_SERVICES **PeiServices,\r
186 IN PEI_SMM_ACCESS_PPI *This,\r
187 IN UINTN DescriptorIndex\r
188 )\r
189/*++\r
190\r
191Routine Description:\r
192\r
193 This routine accepts a request to "lock" SMRAM. The\r
194 region could be legacy AB or TSEG near top of physical memory.\r
195 The use of "lock" means that the memory can no longer be opened\r
196 to PEIM.\r
197\r
198Arguments:\r
199\r
200 PeiServices - General purpose services available to every PEIM.\r
201 This - Pointer to the SMM Access Interface.\r
202 DescriptorIndex - Region of SMRAM to Lock.\r
203\r
204Returns:\r
205\r
206 EFI_SUCCESS - The region was successfully locked.\r
207 EFI_DEVICE_ERROR - The region could not be locked because at least\r
208 one range is still open.\r
209 EFI_INVALID_PARAMETER - The descriptor index was out of bounds.\r
210\r
211--*/\r
212{\r
213 SMM_ACCESS_PRIVATE_DATA *SmmAccess;\r
214\r
215 SmmAccess = SMM_ACCESS_PRIVATE_DATA_FROM_THIS (This);\r
216\r
217 if (DescriptorIndex >= SmmAccess->NumberRegions) {\r
218 return EFI_INVALID_PARAMETER;\r
219 } else if (SmmAccess->SmmAccess.OpenState) {\r
220 return EFI_DEVICE_ERROR;\r
221 }\r
222\r
223 SmmAccess->SmramDesc[DescriptorIndex].RegionState |= EFI_SMRAM_LOCKED;\r
224 SmmAccess->SmmAccess.LockState = TRUE;\r
225\r
226 //\r
227 // Lock TSEG\r
228 //\r
229 QNCLockSmramRegion ();\r
230\r
231 return EFI_SUCCESS;\r
232}\r
233\r
234EFI_STATUS\r
235EFIAPI\r
236GetCapabilities (\r
237 IN EFI_PEI_SERVICES **PeiServices,\r
238 IN PEI_SMM_ACCESS_PPI *This,\r
239 IN OUT UINTN *SmramMapSize,\r
240 IN OUT EFI_SMRAM_DESCRIPTOR *SmramMap\r
241 )\r
242/*++\r
243\r
244Routine Description:\r
245\r
246 This routine services a user request to discover the SMRAM\r
247 capabilities of this platform. This will report the possible\r
248 ranges that are possible for SMRAM access, based upon the\r
249 memory controller capabilities.\r
250\r
251Arguments:\r
252\r
253 PeiServices - General purpose services available to every PEIM.\r
254 This - Pointer to the SMRAM Access Interface.\r
255 SmramMapSize - Pointer to the variable containing size of the\r
256 buffer to contain the description information.\r
257 SmramMap - Buffer containing the data describing the Smram\r
258 region descriptors.\r
259Returns:\r
260\r
261 EFI_BUFFER_TOO_SMALL - The user did not provide a sufficient buffer.\r
262 EFI_SUCCESS - The user provided a sufficiently-sized buffer.\r
263\r
264--*/\r
265{\r
266 EFI_STATUS Status;\r
267 SMM_ACCESS_PRIVATE_DATA *SmmAccess;\r
268 UINTN BufferSize;\r
269\r
270 SmmAccess = SMM_ACCESS_PRIVATE_DATA_FROM_THIS (This);\r
271 BufferSize = SmmAccess->NumberRegions * sizeof (EFI_SMRAM_DESCRIPTOR);\r
272\r
273 if (*SmramMapSize < BufferSize) {\r
274 Status = EFI_BUFFER_TOO_SMALL;\r
275 } else {\r
276 CopyMem (SmramMap, SmmAccess->SmramDesc, *SmramMapSize);\r
277 Status = EFI_SUCCESS;\r
278 }\r
279\r
280 *SmramMapSize = BufferSize;\r
281\r
282 return Status;\r
283}\r
284\r
285\r
286EFI_STATUS\r
287EFIAPI\r
288SmmAccessPeiEntryPoint (\r
289 IN EFI_PEI_FILE_HANDLE FileHandle,\r
290 IN CONST EFI_PEI_SERVICES **PeiServices\r
291 )\r
292/*++\r
293\r
294Routine Description:\r
295\r
296 This is the constructor for the SMM Access Ppi\r
297\r
298Arguments:\r
299\r
300 FfsHeader - FfsHeader.\r
301 PeiServices - General purpose services available to every PEIM.\r
302\r
303Returns:\r
304\r
305 EFI_SUCCESS - Protocol successfully started and installed.\r
306 EFI_UNSUPPORTED - Protocol can't be started.\r
307--*/\r
308{\r
309\r
310 EFI_STATUS Status;\r
311 UINTN Index;\r
312 EFI_SMRAM_HOB_DESCRIPTOR_BLOCK *DescriptorBlock;\r
313 SMM_ACCESS_PRIVATE_DATA *SmmAccessPrivate;\r
314 EFI_PEI_PPI_DESCRIPTOR *PpiList;\r
315 EFI_HOB_GUID_TYPE *GuidHob;\r
316\r
317 //\r
318 // Initialize private data\r
319 //\r
320 SmmAccessPrivate = AllocatePool (sizeof(*SmmAccessPrivate));\r
321 ASSERT(SmmAccessPrivate);\r
322\r
323 PpiList = AllocatePool (sizeof(*PpiList));\r
324 ASSERT (PpiList);\r
325\r
326 //\r
327 // Build SMM related information\r
328 //\r
329 SmmAccessPrivate->Signature = SMM_ACCESS_PRIVATE_DATA_SIGNATURE;\r
330\r
331 //\r
332 // Get Hob list\r
333 //\r
334 GuidHob = GetFirstGuidHob (&gEfiSmmPeiSmramMemoryReserveGuid);\r
335 DescriptorBlock = GET_GUID_HOB_DATA (GuidHob);\r
336 ASSERT (DescriptorBlock);\r
337\r
338 // Get CPU Max bus number\r
339\r
340 SmmAccessPrivate->MaxBusNumber = PCI_BUS_NUMBER_QNC;\r
341 for (Index = 0; Index < MAX_CPU_SOCKET; Index++) {\r
342 SmmAccessPrivate->SocketPopulated[Index] = TRUE;\r
343 SmmAccessPrivate->SocketBusNum[Index] = PCI_BUS_NUMBER_QNC;\r
344 }\r
345\r
346 //\r
347 // Use the hob to publish SMRAM capabilities\r
348 //\r
349 ASSERT (DescriptorBlock->NumberOfSmmReservedRegions <= MAX_SMRAM_RANGES);\r
350 for (Index = 0; Index < DescriptorBlock->NumberOfSmmReservedRegions; Index++) {\r
351 SmmAccessPrivate->SmramDesc[Index].PhysicalStart = DescriptorBlock->Descriptor[Index].PhysicalStart;\r
352 SmmAccessPrivate->SmramDesc[Index].CpuStart = DescriptorBlock->Descriptor[Index].CpuStart;\r
353 SmmAccessPrivate->SmramDesc[Index].PhysicalSize = DescriptorBlock->Descriptor[Index].PhysicalSize;\r
354 SmmAccessPrivate->SmramDesc[Index].RegionState = DescriptorBlock->Descriptor[Index].RegionState;\r
355 }\r
356\r
357 SmmAccessPrivate->NumberRegions = Index;\r
358 SmmAccessPrivate->SmmAccess.Open = Open;\r
359 SmmAccessPrivate->SmmAccess.Close = Close;\r
360 SmmAccessPrivate->SmmAccess.Lock = Lock;\r
361 SmmAccessPrivate->SmmAccess.GetCapabilities = GetCapabilities;\r
362 SmmAccessPrivate->SmmAccess.LockState = FALSE;\r
363 SmmAccessPrivate->SmmAccess.OpenState = FALSE;\r
364\r
365 PpiList->Flags = (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST);\r
366 PpiList->Guid = &gPeiSmmAccessPpiGuid;\r
367 PpiList->Ppi = &SmmAccessPrivate->SmmAccess;\r
368\r
369 Status = (**PeiServices).InstallPpi (PeiServices, PpiList);\r
370 ASSERT_EFI_ERROR(Status);\r
371\r
372 DEBUG (\r
373 (EFI_D_INFO, "SMM Base:Size %08X:%08X\n",\r
374 (UINTN)(SmmAccessPrivate->SmramDesc[SmmAccessPrivate->NumberRegions-1].PhysicalStart),\r
375 (UINTN)(SmmAccessPrivate->SmramDesc[SmmAccessPrivate->NumberRegions-1].PhysicalSize)\r
376 ));\r
377\r
378 SmmAccessPrivate->TsegSize = (UINT8)(SmmAccessPrivate->SmramDesc[SmmAccessPrivate->NumberRegions-1].PhysicalSize);\r
379\r
380 return EFI_SUCCESS;\r
381}\r
382\r