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