]> git.proxmox.com Git - mirror_edk2.git/blame_incremental - QuarkSocPkg/QuarkNorthCluster/Smm/Dxe/SmmAccessDxe/SmmAccessDriver.c
QuarkSocPkg: Add new package for Quark SoC X1000
[mirror_edk2.git] / QuarkSocPkg / QuarkNorthCluster / Smm / Dxe / SmmAccessDxe / SmmAccessDriver.c
... / ...
CommitLineData
1/** @file\r
2This is the driver that publishes the SMM Access Protocol\r
3instance for the Tylersburg chipset.\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\r
17#include "SmmAccessDriver.h"\r
18\r
19\r
20\r
21SMM_ACCESS_PRIVATE_DATA mSmmAccess;\r
22\r
23VOID\r
24SmmAccessOnBoot (\r
25 IN EFI_EVENT Event,\r
26 IN VOID *Context\r
27);\r
28\r
29EFI_STATUS\r
30EFIAPI\r
31SmmAccessDriverEntryPoint (\r
32 IN EFI_HANDLE ImageHandle,\r
33 IN EFI_SYSTEM_TABLE *SystemTable\r
34 )\r
35/*++\r
36\r
37Routine Description:\r
38\r
39 Installs an SMM Access Protocol.\r
40\r
41Arguments:\r
42\r
43 ImageHandle - Handle for the image of this driver.\r
44 SystemTable - Pointer to the EFI System Table.\r
45\r
46Returns:\r
47\r
48 EFI_SUCCESS - Protocol successfully started and installed.\r
49 EFI_UNSUPPORTED - Protocol can't be started.\r
50 EFI_NOT_FOUND - Protocol not found.\r
51--*/\r
52{\r
53\r
54 EFI_STATUS Status;\r
55 EFI_EVENT BootEvent;\r
56 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;\r
57 UINTN Index;\r
58 EFI_SMRAM_HOB_DESCRIPTOR_BLOCK *DescriptorBlock;\r
59 EFI_HOB_GUID_TYPE *GuidHob;\r
60\r
61\r
62 //\r
63 // Initialize private data\r
64 //\r
65 ZeroMem (&mSmmAccess, sizeof (mSmmAccess));\r
66\r
67 Status = gBS->LocateProtocol (\r
68 &gEfiPciRootBridgeIoProtocolGuid,\r
69 NULL,\r
70 (VOID **) &PciRootBridgeIo\r
71 );\r
72 ASSERT_EFI_ERROR (Status);\r
73\r
74 //\r
75 // Build SMM related information\r
76 //\r
77 mSmmAccess.Signature = SMM_ACCESS_PRIVATE_DATA_SIGNATURE;\r
78 mSmmAccess.Handle = NULL;\r
79 mSmmAccess.PciRootBridgeIo = PciRootBridgeIo;\r
80\r
81 //\r
82 // Get Hob list\r
83 //\r
84 GuidHob = GetFirstGuidHob (&gEfiSmmPeiSmramMemoryReserveGuid);\r
85 DescriptorBlock = GET_GUID_HOB_DATA (GuidHob);\r
86 ASSERT (DescriptorBlock);\r
87\r
88\r
89 //\r
90 // Get CPU Max bus number\r
91 //\r
92 mSmmAccess.MaxBusNumber = PCI_BUS_NUMBER_QNC;\r
93 for (Index = 0; Index < MAX_CPU_SOCKET; Index++) {\r
94 mSmmAccess.SocketPopulated[Index] = TRUE;\r
95 }\r
96\r
97 //\r
98 // Use the hob to publish SMRAM capabilities\r
99 //\r
100 ASSERT (DescriptorBlock->NumberOfSmmReservedRegions <= MAX_SMRAM_RANGES);\r
101 for (Index = 0; Index < DescriptorBlock->NumberOfSmmReservedRegions; Index++) {\r
102 mSmmAccess.SmramDesc[Index].PhysicalStart = DescriptorBlock->Descriptor[Index].PhysicalStart;\r
103 mSmmAccess.SmramDesc[Index].CpuStart = DescriptorBlock->Descriptor[Index].CpuStart;\r
104 mSmmAccess.SmramDesc[Index].PhysicalSize = DescriptorBlock->Descriptor[Index].PhysicalSize;\r
105 mSmmAccess.SmramDesc[Index].RegionState = DescriptorBlock->Descriptor[Index].RegionState;\r
106 DEBUG ((EFI_D_INFO, "SM RAM index[%d] startaddr:%08X Size :%08X\n", Index, mSmmAccess.SmramDesc[Index].CpuStart,\r
107 mSmmAccess.SmramDesc[Index].PhysicalSize));\r
108 }\r
109\r
110 mSmmAccess.NumberRegions = Index;\r
111 mSmmAccess.SmmAccess.Open = Open;\r
112 mSmmAccess.SmmAccess.Close = Close;\r
113 mSmmAccess.SmmAccess.Lock = Lock;\r
114 mSmmAccess.SmmAccess.GetCapabilities = GetCapabilities;\r
115 mSmmAccess.SmmAccess.LockState = FALSE;\r
116 mSmmAccess.SmmAccess.OpenState = FALSE;\r
117 mSmmAccess.SMMRegionState = EFI_SMRAM_CLOSED;\r
118\r
119 //\r
120 // Install our protocol interfaces on the device's handle\r
121 //\r
122 Status = gBS->InstallMultipleProtocolInterfaces (\r
123 &mSmmAccess.Handle,\r
124 &gEfiSmmAccess2ProtocolGuid,\r
125 &mSmmAccess.SmmAccess,\r
126 NULL\r
127 );\r
128 ASSERT_EFI_ERROR (Status);\r
129\r
130 DEBUG ((EFI_D_INFO, "SMM Base: %08X\n", (UINT32)(mSmmAccess.SmramDesc[mSmmAccess.NumberRegions-1].PhysicalStart)));\r
131 DEBUG ((EFI_D_INFO, "SMM Size: %08X\n", (UINT32)(mSmmAccess.SmramDesc[mSmmAccess.NumberRegions-1].PhysicalSize)));\r
132\r
133 mSmmAccess.TsegSize = (UINT8)(mSmmAccess.SmramDesc[mSmmAccess.NumberRegions-1].PhysicalSize);\r
134 //\r
135 // T Seg setting done in QPI RC\r
136 //\r
137\r
138 //\r
139 // Prior ReadyToBoot, lock CSEG\r
140 //\r
141 Status = EfiCreateEventReadyToBootEx(\r
142 TPL_NOTIFY,\r
143 SmmAccessOnBoot,\r
144 NULL,\r
145 &BootEvent );\r
146 ASSERT (!EFI_ERROR (Status));\r
147 return EFI_SUCCESS;\r
148}\r
149\r
150EFI_STATUS\r
151EFIAPI\r
152Open (\r
153 IN EFI_SMM_ACCESS2_PROTOCOL *This\r
154 )\r
155/*++\r
156\r
157Routine Description:\r
158\r
159 This routine accepts a request to "open" a region of SMRAM. The\r
160 region could be legacy ABSEG, HSEG, or TSEG near top of physical memory.\r
161 The use of "open" means that the memory is visible from all boot-service\r
162 and SMM agents.\r
163\r
164Arguments:\r
165\r
166 This - Pointer to the SMM Access Interface.\r
167 DescriptorIndex - Region of SMRAM to Open.\r
168\r
169Returns:\r
170\r
171 EFI_SUCCESS - The region was successfully opened.\r
172 EFI_DEVICE_ERROR - The region could not be opened because locked by\r
173 chipset.\r
174 EFI_INVALID_PARAMETER - The descriptor index was out of bounds.\r
175\r
176--*/\r
177{\r
178 SMM_ACCESS_PRIVATE_DATA *SmmAccess;\r
179\r
180 SmmAccess = SMM_ACCESS_PRIVATE_DATA_FROM_THIS (This);\r
181\r
182 if (mSmmAccess.SMMRegionState & EFI_SMRAM_LOCKED) {\r
183 DEBUG ((EFI_D_ERROR, "Cannot open a locked SMRAM region\n"));\r
184 return EFI_DEVICE_ERROR;\r
185 }\r
186\r
187 //\r
188 // Open TSEG\r
189 //\r
190 if (!QNCOpenSmramRegion ()) {\r
191 mSmmAccess.SMMRegionState |= EFI_SMRAM_LOCKED;\r
192 return EFI_DEVICE_ERROR;\r
193 }\r
194\r
195 mSmmAccess.SMMRegionState &= ~(EFI_SMRAM_CLOSED | EFI_ALLOCATED);\r
196 SyncRegionState2SmramDesc(FALSE, (UINT64)(UINTN)(~(EFI_SMRAM_CLOSED | EFI_ALLOCATED)));\r
197 mSmmAccess.SMMRegionState |= EFI_SMRAM_OPEN;\r
198 SyncRegionState2SmramDesc(TRUE, EFI_SMRAM_OPEN);\r
199 SmmAccess->SmmAccess.OpenState = TRUE;\r
200\r
201 return EFI_SUCCESS;\r
202}\r
203\r
204EFI_STATUS\r
205EFIAPI\r
206Close (\r
207 IN EFI_SMM_ACCESS2_PROTOCOL *This\r
208 )\r
209/*++\r
210\r
211Routine Description:\r
212\r
213 This routine accepts a request to "close" a region of SMRAM. This is valid for\r
214 compatible SMRAM region.\r
215\r
216Arguments:\r
217\r
218 This - Pointer to the SMM Access Interface.\r
219 DescriptorIndex - Region of SMRAM to Close.\r
220\r
221Returns:\r
222\r
223 EFI_SUCCESS - The region was successfully closed.\r
224 EFI_DEVICE_ERROR - The region could not be closed because locked by\r
225 chipset.\r
226 EFI_INVALID_PARAMETER - The descriptor index was out of bounds.\r
227\r
228--*/\r
229{\r
230 SMM_ACCESS_PRIVATE_DATA *SmmAccess;\r
231 BOOLEAN OpenState;\r
232 UINTN Index;\r
233\r
234 SmmAccess = SMM_ACCESS_PRIVATE_DATA_FROM_THIS (This);\r
235\r
236 if (mSmmAccess.SMMRegionState & EFI_SMRAM_LOCKED) {\r
237 //\r
238 // Cannot close a "locked" region\r
239 //\r
240 DEBUG ((EFI_D_WARN, "Cannot close the locked SMRAM Region\n"));\r
241 return EFI_DEVICE_ERROR;\r
242 }\r
243\r
244 if (mSmmAccess.SMMRegionState & EFI_SMRAM_CLOSED) {\r
245 return EFI_DEVICE_ERROR;\r
246 }\r
247\r
248 //\r
249 // Close TSEG\r
250 //\r
251 if (!QNCCloseSmramRegion ()) {\r
252 mSmmAccess.SMMRegionState |= EFI_SMRAM_LOCKED;\r
253 return EFI_DEVICE_ERROR;\r
254 }\r
255\r
256 mSmmAccess.SMMRegionState &= ~EFI_SMRAM_OPEN;\r
257 SyncRegionState2SmramDesc(FALSE, (UINT64)(UINTN)(~EFI_SMRAM_OPEN));\r
258 mSmmAccess.SMMRegionState |= (EFI_SMRAM_CLOSED | EFI_ALLOCATED);\r
259 SyncRegionState2SmramDesc(TRUE, EFI_SMRAM_CLOSED | EFI_ALLOCATED);\r
260\r
261 //\r
262 // Find out if any regions are still open\r
263 //\r
264 OpenState = FALSE;\r
265 for (Index = 0; Index < mSmmAccess.NumberRegions; Index++) {\r
266 if ((SmmAccess->SmramDesc[Index].RegionState & EFI_SMRAM_OPEN) == EFI_SMRAM_OPEN) {\r
267 OpenState = TRUE;\r
268 }\r
269 }\r
270\r
271 SmmAccess->SmmAccess.OpenState = OpenState;\r
272\r
273 return EFI_SUCCESS;\r
274}\r
275\r
276EFI_STATUS\r
277EFIAPI\r
278Lock (\r
279 IN EFI_SMM_ACCESS2_PROTOCOL *This\r
280 )\r
281/*++\r
282\r
283Routine Description:\r
284\r
285 This routine accepts a request to "lock" SMRAM. The\r
286 region could be legacy AB or TSEG near top of physical memory.\r
287 The use of "lock" means that the memory can no longer be opened\r
288 to BS state..\r
289\r
290Arguments:\r
291\r
292 This - Pointer to the SMM Access Interface.\r
293 DescriptorIndex - Region of SMRAM to Lock.\r
294\r
295Returns:\r
296\r
297 EFI_SUCCESS - The region was successfully locked.\r
298 EFI_DEVICE_ERROR - The region could not be locked because at least\r
299 one range is still open.\r
300 EFI_INVALID_PARAMETER - The descriptor index was out of bounds.\r
301\r
302--*/\r
303{\r
304 SMM_ACCESS_PRIVATE_DATA *SmmAccess;\r
305\r
306 SmmAccess = SMM_ACCESS_PRIVATE_DATA_FROM_THIS (This);\r
307\r
308 if (SmmAccess->SmmAccess.OpenState) {\r
309 return EFI_DEVICE_ERROR;\r
310 }\r
311\r
312 mSmmAccess.SMMRegionState |= EFI_SMRAM_LOCKED;\r
313 SyncRegionState2SmramDesc(TRUE, EFI_SMRAM_LOCKED);\r
314 SmmAccess->SmmAccess.LockState = TRUE;\r
315\r
316 //\r
317 // Lock TSEG\r
318 //\r
319 QNCLockSmramRegion ();\r
320\r
321 return EFI_SUCCESS;\r
322}\r
323\r
324EFI_STATUS\r
325EFIAPI\r
326GetCapabilities (\r
327 IN CONST EFI_SMM_ACCESS2_PROTOCOL *This,\r
328 IN OUT UINTN *SmramMapSize,\r
329 IN OUT EFI_SMRAM_DESCRIPTOR *SmramMap\r
330 )\r
331/*++\r
332\r
333Routine Description:\r
334\r
335 This routine services a user request to discover the SMRAM\r
336 capabilities of this platform. This will report the possible\r
337 ranges that are possible for SMRAM access, based upon the\r
338 memory controller capabilities.\r
339\r
340Arguments:\r
341\r
342 This - Pointer to the SMRAM Access Interface.\r
343 SmramMapSize - Pointer to the variable containing size of the\r
344 buffer to contain the description information.\r
345 SmramMap - Buffer containing the data describing the Smram\r
346 region descriptors.\r
347Returns:\r
348\r
349 EFI_BUFFER_TOO_SMALL - The user did not provide a sufficient buffer.\r
350 EFI_SUCCESS - The user provided a sufficiently-sized buffer.\r
351\r
352--*/\r
353{\r
354 EFI_STATUS Status;\r
355 SMM_ACCESS_PRIVATE_DATA *SmmAccess;\r
356 UINTN BufferSize;\r
357\r
358 SmmAccess = SMM_ACCESS_PRIVATE_DATA_FROM_THIS (This);\r
359 BufferSize = SmmAccess->NumberRegions * sizeof (EFI_SMRAM_DESCRIPTOR);\r
360\r
361 if (*SmramMapSize < BufferSize) {\r
362 Status = EFI_BUFFER_TOO_SMALL;\r
363 } else {\r
364 CopyMem (SmramMap, SmmAccess->SmramDesc, *SmramMapSize);\r
365 Status = EFI_SUCCESS;\r
366 }\r
367 *SmramMapSize = BufferSize;\r
368\r
369 return Status;\r
370}\r
371\r
372VOID\r
373SmmAccessOnBoot (\r
374 IN EFI_EVENT Event,\r
375 IN VOID *Context\r
376)\r
377{\r
378\r
379}\r
380VOID\r
381SyncRegionState2SmramDesc(\r
382 IN BOOLEAN OrAnd,\r
383 IN UINT64 Value\r
384 )\r
385{\r
386 UINT32 Index;\r
387\r
388 for (Index = 0; Index < mSmmAccess.NumberRegions; Index++) {\r
389 if (OrAnd) {\r
390 mSmmAccess.SmramDesc[Index].RegionState |= Value;\r
391 } else {\r
392 mSmmAccess.SmramDesc[Index].RegionState &= Value;\r
393 }\r
394 }\r
395}\r