]> git.proxmox.com Git - mirror_edk2.git/blob - QuarkSocPkg/QuarkNorthCluster/Smm/Dxe/SmmAccessDxe/SmmAccessDriver.c
QuarkSocPkg: Replace BSD License with BSD+Patent License
[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-2015 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 SMM_ACCESS_PRIVATE_DATA *SmmAccess;
225 BOOLEAN OpenState;
226 UINTN Index;
227
228 SmmAccess = SMM_ACCESS_PRIVATE_DATA_FROM_THIS (This);
229
230 if (mSmmAccess.SMMRegionState & EFI_SMRAM_LOCKED) {
231 //
232 // Cannot close a "locked" region
233 //
234 DEBUG ((EFI_D_WARN, "Cannot close the locked SMRAM Region\n"));
235 return EFI_DEVICE_ERROR;
236 }
237
238 if (mSmmAccess.SMMRegionState & EFI_SMRAM_CLOSED) {
239 return EFI_DEVICE_ERROR;
240 }
241
242 //
243 // Close TSEG
244 //
245 if (!QNCCloseSmramRegion ()) {
246 mSmmAccess.SMMRegionState |= EFI_SMRAM_LOCKED;
247 return EFI_DEVICE_ERROR;
248 }
249
250 mSmmAccess.SMMRegionState &= ~EFI_SMRAM_OPEN;
251 SyncRegionState2SmramDesc(FALSE, (UINT64)(UINTN)(~EFI_SMRAM_OPEN));
252 mSmmAccess.SMMRegionState |= (EFI_SMRAM_CLOSED | EFI_ALLOCATED);
253 SyncRegionState2SmramDesc(TRUE, EFI_SMRAM_CLOSED | EFI_ALLOCATED);
254
255 //
256 // Find out if any regions are still open
257 //
258 OpenState = FALSE;
259 for (Index = 0; Index < mSmmAccess.NumberRegions; Index++) {
260 if ((SmmAccess->SmramDesc[Index].RegionState & EFI_SMRAM_OPEN) == EFI_SMRAM_OPEN) {
261 OpenState = TRUE;
262 }
263 }
264
265 SmmAccess->SmmAccess.OpenState = OpenState;
266
267 return EFI_SUCCESS;
268 }
269
270 EFI_STATUS
271 EFIAPI
272 Lock (
273 IN EFI_SMM_ACCESS2_PROTOCOL *This
274 )
275 /*++
276
277 Routine Description:
278
279 This routine accepts a request to "lock" SMRAM. The
280 region could be legacy AB or TSEG near top of physical memory.
281 The use of "lock" means that the memory can no longer be opened
282 to BS state..
283
284 Arguments:
285
286 This - Pointer to the SMM Access Interface.
287 DescriptorIndex - Region of SMRAM to Lock.
288
289 Returns:
290
291 EFI_SUCCESS - The region was successfully locked.
292 EFI_DEVICE_ERROR - The region could not be locked because at least
293 one range is still open.
294 EFI_INVALID_PARAMETER - The descriptor index was out of bounds.
295
296 --*/
297 {
298 SMM_ACCESS_PRIVATE_DATA *SmmAccess;
299
300 SmmAccess = SMM_ACCESS_PRIVATE_DATA_FROM_THIS (This);
301
302 if (SmmAccess->SmmAccess.OpenState) {
303 return EFI_DEVICE_ERROR;
304 }
305
306 mSmmAccess.SMMRegionState |= EFI_SMRAM_LOCKED;
307 SyncRegionState2SmramDesc(TRUE, EFI_SMRAM_LOCKED);
308 SmmAccess->SmmAccess.LockState = TRUE;
309
310 //
311 // Lock TSEG
312 //
313 QNCLockSmramRegion ();
314
315 return EFI_SUCCESS;
316 }
317
318 EFI_STATUS
319 EFIAPI
320 GetCapabilities (
321 IN CONST EFI_SMM_ACCESS2_PROTOCOL *This,
322 IN OUT UINTN *SmramMapSize,
323 IN OUT EFI_SMRAM_DESCRIPTOR *SmramMap
324 )
325 /*++
326
327 Routine Description:
328
329 This routine services a user request to discover the SMRAM
330 capabilities of this platform. This will report the possible
331 ranges that are possible for SMRAM access, based upon the
332 memory controller capabilities.
333
334 Arguments:
335
336 This - Pointer to the SMRAM Access Interface.
337 SmramMapSize - Pointer to the variable containing size of the
338 buffer to contain the description information.
339 SmramMap - Buffer containing the data describing the Smram
340 region descriptors.
341 Returns:
342
343 EFI_BUFFER_TOO_SMALL - The user did not provide a sufficient buffer.
344 EFI_SUCCESS - The user provided a sufficiently-sized buffer.
345
346 --*/
347 {
348 EFI_STATUS Status;
349 SMM_ACCESS_PRIVATE_DATA *SmmAccess;
350 UINTN BufferSize;
351
352 SmmAccess = SMM_ACCESS_PRIVATE_DATA_FROM_THIS (This);
353 BufferSize = SmmAccess->NumberRegions * sizeof (EFI_SMRAM_DESCRIPTOR);
354
355 if (*SmramMapSize < BufferSize) {
356 Status = EFI_BUFFER_TOO_SMALL;
357 } else {
358 CopyMem (SmramMap, SmmAccess->SmramDesc, *SmramMapSize);
359 Status = EFI_SUCCESS;
360 }
361 *SmramMapSize = BufferSize;
362
363 return Status;
364 }
365
366 VOID
367 SmmAccessOnBoot (
368 IN EFI_EVENT Event,
369 IN VOID *Context
370 )
371 {
372
373 }
374 VOID
375 SyncRegionState2SmramDesc(
376 IN BOOLEAN OrAnd,
377 IN UINT64 Value
378 )
379 {
380 UINT32 Index;
381
382 for (Index = 0; Index < mSmmAccess.NumberRegions; Index++) {
383 if (OrAnd) {
384 mSmmAccess.SmramDesc[Index].RegionState |= Value;
385 } else {
386 mSmmAccess.SmramDesc[Index].RegionState &= Value;
387 }
388 }
389 }