• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
Open(IN EFI_PEI_SERVICES ** PeiServices,IN PEI_SMM_ACCESS_PPI * This,IN UINTN DescriptorIndex)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
Close(IN EFI_PEI_SERVICES ** PeiServices,IN PEI_SMM_ACCESS_PPI * This,IN UINTN DescriptorIndex)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
Lock(IN EFI_PEI_SERVICES ** PeiServices,IN PEI_SMM_ACCESS_PPI * This,IN UINTN DescriptorIndex)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
GetCapabilities(IN EFI_PEI_SERVICES ** PeiServices,IN PEI_SMM_ACCESS_PPI * This,IN OUT UINTN * SmramMapSize,IN OUT EFI_SMRAM_DESCRIPTOR * SmramMap)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
SmmAccessPeiEntryPoint(IN EFI_PEI_FILE_HANDLE FileHandle,IN CONST EFI_PEI_SERVICES ** PeiServices)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 
383