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