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