1 /** @file
2 
3   Copyright (c) 2004  - 2014, Intel Corporation. All rights reserved.<BR>
4 
5 
6   This program and the accompanying materials are licensed and made available under
7 
8   the terms and conditions of the BSD License that accompanies this distribution.
9 
10   The full text of the license may be found at
11 
12   http://opensource.org/licenses/bsd-license.php.
13 
14 
15 
16   THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
17 
18   WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
19 
20 
21 
22 
23 Module Name:
24 
25 
26   MemoryPeim.c
27 
28 Abstract:
29 
30   Tiano PEIM to provide the platform support functionality.
31   This file implements the Platform Memory Range PPI
32 
33 --*/
34 
35 #include "PlatformEarlyInit.h"
36 
37 //
38 // Need min. of 48MB PEI phase
39 //
40 #define  PEI_MIN_MEMORY_SIZE               (6 * 0x800000)
41 #define  PEI_RECOVERY_MIN_MEMORY_SIZE      (6 * 0x800000)
42 
43 //
44 // This is the memory needed for PEI to start up DXE.
45 //
46 // Over-estimating this size will lead to higher fragmentation
47 // of main memory.  Under-estimation of this will cause catastrophic
48 // failure of PEI to load DXE.  Generally, the failure may only be
49 // realized during capsule updates.
50 //
51 #define PRERESERVED_PEI_MEMORY ( \
52   EFI_SIZE_TO_PAGES (3 * 0x800000)   /* PEI Core memory based stack          */ \
53   )
54 
55 EFI_MEMORY_TYPE_INFORMATION mDefaultMemoryTypeInformation[] = {
56   { EfiACPIReclaimMemory,       0x40  },    // 0x40 pages = 256k for ASL
57   { EfiACPIMemoryNVS,           0x100 },    // 0x100 pages = 1 MB for S3, SMM, HII, etc
58   { EfiReservedMemoryType,      0x600 },    // 48k for BIOS Reserved
59   { EfiMemoryMappedIO,          0     },
60   { EfiMemoryMappedIOPortSpace, 0     },
61   { EfiPalCode,                 0     },
62   { EfiRuntimeServicesCode,     0x200 },
63   { EfiRuntimeServicesData,     0x100 },
64   { EfiLoaderCode,              0x100 },
65   { EfiLoaderData,              0x100 },
66   { EfiBootServicesCode,        0x800 },
67   { EfiBootServicesData,        0x2500},
68   { EfiConventionalMemory,      0     },
69   { EfiUnusableMemory,          0     },
70   { EfiMaxMemoryType,           0     }
71 };
72 
73 STATIC
74 EFI_STATUS
75 GetMemorySize (
SetPeiCacheMode(IN CONST EFI_PEI_SERVICES ** PeiServices)76   IN  CONST EFI_PEI_SERVICES    **PeiServices,
77   OUT UINT64              *LowMemoryLength,
78   OUT UINT64              *HighMemoryLength
79   );
80 
81 
82 
83 EFI_STATUS
84 EFIAPI
85 SetPeiCacheMode (
86   IN  CONST EFI_PEI_SERVICES    **PeiServices
87   )
88 {
89   EFI_STATUS              Status;
90   PEI_CACHE_PPI           *CachePpi;
91 
92   EFI_BOOT_MODE           BootMode;
93   UINT64                  MemoryLength;
94   UINT64                  MemOverflow;
95   UINT64                  MemoryLengthUc;
96   UINT64                  MaxMemoryLength;
97   UINT64                  LowMemoryLength;
98   UINT64                  HighMemoryLength;
99   UINT8                   Index;
100   MTRR_SETTINGS           MtrrSetting;
101 
102   //
103   // Load Cache PPI
104   //
105   Status = (**PeiServices).LocatePpi (
106              PeiServices,
107              &gPeiCachePpiGuid,    // GUID
108              0,                    // Instance
109              NULL,                 // EFI_PEI_PPI_DESCRIPTOR
110              (void **)&CachePpi             // PPI
111              );
112   if (!EFI_ERROR(Status)) {
113     //
114     // Clear the CAR Settings (Default Cache Type => UC)
115     //
116     DEBUG ((EFI_D_INFO, "Reset cache attribute and disable CAR. \n"));
117     CachePpi->ResetCache(
118                 (EFI_PEI_SERVICES**)PeiServices,
119                 CachePpi
120                 );
121  }
122 
123 
124   //
125   // Variable initialization
126   //
127   LowMemoryLength = 0;
128   HighMemoryLength = 0;
129   MemoryLengthUc = 0;
130 
131   Status = (*PeiServices)->GetBootMode (
132                              PeiServices,
133                              &BootMode
134                              );
135 
136   //
137   // Determine memory usage
138   //
139   GetMemorySize (
140     PeiServices,
141     &LowMemoryLength,
142     &HighMemoryLength
143     );
144 
145   LowMemoryLength  = (EFI_PHYSICAL_ADDRESS)MmPci32( 0, 0, 2, 0, 0x70);
146   LowMemoryLength   &=  0xFFF00000ULL;
147 
148   MaxMemoryLength = LowMemoryLength;
149 
150   //
151   // Round up to nearest 256MB with high memory and 64MB w/o high memory
152   //
153   if (HighMemoryLength != 0 ) {
154     MemOverflow = (LowMemoryLength & 0x0fffffff);
155     if (MemOverflow != 0) {
156       MaxMemoryLength = LowMemoryLength + (0x10000000 - MemOverflow);
157     }
158   } else {
159     MemOverflow = (LowMemoryLength & 0x03ffffff);
160     if (MemOverflow != 0) {
161       MaxMemoryLength = LowMemoryLength + (0x4000000 - MemOverflow);
162     }
163   }
164 
165   ZeroMem (&MtrrSetting, sizeof(MTRR_SETTINGS));
166   for (Index = 0; Index < 2; Index++) {
167     MtrrSetting.Fixed.Mtrr[Index]=0x0606060606060606;
168    }
169   for (Index = 2; Index < 11; Index++) {
170     MtrrSetting.Fixed.Mtrr[Index]=0x0505050505050505;
171    }
172 
173   //
174   // Cache the flash area to improve the boot performance in PEI phase
175   //
176   Index = 0;
177   MtrrSetting.Variables.Mtrr[0].Base = (FixedPcdGet32 (PcdFlashAreaBaseAddress) | CacheWriteProtected);
178   MtrrSetting.Variables.Mtrr[0].Mask = ((~((UINT64)(FixedPcdGet32 (PcdFlashAreaSize) - 1))) & MTRR_LIB_CACHE_VALID_ADDRESS) | MTRR_LIB_CACHE_MTRR_ENABLED;
179   Index ++;
180 
181   MemOverflow =0;
182   while (MaxMemoryLength > MemOverflow){
183     MtrrSetting.Variables.Mtrr[Index].Base = (MemOverflow & MTRR_LIB_CACHE_VALID_ADDRESS) | CacheWriteBack;
184     MemoryLength = MaxMemoryLength - MemOverflow;
185     MemoryLength = GetPowerOfTwo64 (MemoryLength);
186     MtrrSetting.Variables.Mtrr[Index].Mask = ((~(MemoryLength - 1)) & MTRR_LIB_CACHE_VALID_ADDRESS) | MTRR_LIB_CACHE_MTRR_ENABLED;
187 
188     MemOverflow += MemoryLength;
189     Index++;
190   }
191 
192   MemoryLength = LowMemoryLength;
193 
194   while (MaxMemoryLength != MemoryLength) {
195     MemoryLengthUc = GetPowerOfTwo64 (MaxMemoryLength - MemoryLength);
196 
197     MtrrSetting.Variables.Mtrr[Index].Base = ((MaxMemoryLength - MemoryLengthUc) & MTRR_LIB_CACHE_VALID_ADDRESS) | CacheUncacheable;
198     MtrrSetting.Variables.Mtrr[Index].Mask= ((~(MemoryLengthUc   - 1)) & MTRR_LIB_CACHE_VALID_ADDRESS) | MTRR_LIB_CACHE_MTRR_ENABLED;
199     MaxMemoryLength -= MemoryLengthUc;
200     Index++;
201   }
202 
203   MemOverflow =0x100000000;
204   while (HighMemoryLength > 0) {
205     MtrrSetting.Variables.Mtrr[Index].Base = (MemOverflow & MTRR_LIB_CACHE_VALID_ADDRESS) | CacheWriteBack;
206     MemoryLength = HighMemoryLength;
207     MemoryLength = GetPowerOfTwo64 (MemoryLength);
208 
209     if (MemoryLength > MemOverflow){
210       MemoryLength = MemOverflow;
211     }
212 
213     MtrrSetting.Variables.Mtrr[Index].Mask = ((~(MemoryLength - 1)) & MTRR_LIB_CACHE_VALID_ADDRESS) | MTRR_LIB_CACHE_MTRR_ENABLED;
214 
215     MemOverflow += MemoryLength;
216     HighMemoryLength -= MemoryLength;
217     Index++;
218   }
219 
220 
221   for (Index = 0; Index < MTRR_NUMBER_OF_VARIABLE_MTRR; Index++) {
222     if (MtrrSetting.Variables.Mtrr[Index].Base == 0){
223       break;
224     }
225     DEBUG ((EFI_D_INFO, "Base=%lx, Mask=%lx\n",MtrrSetting.Variables.Mtrr[Index].Base ,MtrrSetting.Variables.Mtrr[Index].Mask));
226   }
227 
228   //
229   // set FE/E bits for IA32_MTRR_DEF_TYPE
230   //
231   MtrrSetting.MtrrDefType |=  3 <<10;
232 
SetDxeCacheMode(IN CONST EFI_PEI_SERVICES ** PeiServices)233   MtrrSetAllMtrrs(&MtrrSetting);
234 
235 
236 
237   return EFI_SUCCESS;
238 }
239 
240 EFI_STATUS
241 EFIAPI
242 SetDxeCacheMode (
243   IN  CONST EFI_PEI_SERVICES    **PeiServices
244   )
GetMemorySize(IN CONST EFI_PEI_SERVICES ** PeiServices,OUT UINT64 * LowMemoryLength,OUT UINT64 * HighMemoryLength)245 {
246   //
247   // This is not needed for now.
248   //
249   return EFI_SUCCESS;
250 }
251 
252 STATIC
253 EFI_STATUS
254 GetMemorySize (
255   IN  CONST EFI_PEI_SERVICES    **PeiServices,
256   OUT UINT64              *LowMemoryLength,
257   OUT UINT64              *HighMemoryLength
258   )
259 {
260   EFI_STATUS              Status;
261   EFI_PEI_HOB_POINTERS    Hob;
262 
263   *HighMemoryLength = 0;
264   *LowMemoryLength = 0x100000;
265 
266   //
267   // Get the HOB list for processing
268   //
269   Status = (*PeiServices)->GetHobList (PeiServices, (void **)&Hob.Raw);
270   if (EFI_ERROR(Status)) {
271     return Status;
272   }
273 
274   //
275   // Collect memory ranges
276   //
277   while (!END_OF_HOB_LIST (Hob)) {
278     if (Hob.Header->HobType == EFI_HOB_TYPE_RESOURCE_DESCRIPTOR) {
279       if (Hob.ResourceDescriptor->ResourceType == EFI_RESOURCE_SYSTEM_MEMORY) {
280         //
281         // Need memory above 1MB to be collected here
282         //
283         if (Hob.ResourceDescriptor->PhysicalStart >= 0x100000 &&
284             Hob.ResourceDescriptor->PhysicalStart < (EFI_PHYSICAL_ADDRESS) 0x100000000) {
285           *LowMemoryLength += (UINT64) (Hob.ResourceDescriptor->ResourceLength);
286         } else if (Hob.ResourceDescriptor->PhysicalStart >= (EFI_PHYSICAL_ADDRESS) 0x100000000) {
287           *HighMemoryLength += (UINT64) (Hob.ResourceDescriptor->ResourceLength);
288         }
289       }
290     }
291     Hob.Raw = GET_NEXT_HOB (Hob);
292   }
293 
294   return EFI_SUCCESS;
295 }
296 
297 
298 /**
299   Publish Memory Type Information.
PublishMemoryTypeInfo(void)300 
301   @param  NULL
302 
303   @retval EFI_SUCCESS    Success.
304   @retval Others         Errors have occurred.
305 **/
306 
307 EFI_STATUS
308 EFIAPI
309 PublishMemoryTypeInfo (
310   void
311   )
312 {
313   EFI_STATUS                      Status;
314   EFI_PEI_READ_ONLY_VARIABLE2_PPI *Variable;
315   UINTN                           DataSize;
316   EFI_MEMORY_TYPE_INFORMATION     MemoryData[EfiMaxMemoryType + 1];
317 
318   Status = PeiServicesLocatePpi (
319              &gEfiPeiReadOnlyVariable2PpiGuid,
320              0,
321              NULL,
322             (void **)&Variable
323              );
324   if (EFI_ERROR(Status)) {
325     DEBUG((EFI_D_ERROR, "WARNING: Locating Pei variable failed 0x%x \n", Status));
326     DEBUG((EFI_D_ERROR, "Build Hob from default\n"));
327     //
328     // Build the default GUID'd HOB for DXE
329     //
330     BuildGuidDataHob (
331       &gEfiMemoryTypeInformationGuid,
332       mDefaultMemoryTypeInformation,
333       sizeof (mDefaultMemoryTypeInformation)
334       );
335 
336     return Status;
337   }
338 
339 
340   DataSize = sizeof (MemoryData);
341 
342   //
343   // This variable is saved in BDS stage. Now read it back
344   //
345   Status = Variable->GetVariable (
346                        Variable,
347                        EFI_MEMORY_TYPE_INFORMATION_VARIABLE_NAME,
348                        &gEfiMemoryTypeInformationGuid,
349                        NULL,
350                        &DataSize,
351                        &MemoryData
352                        );
353   if (EFI_ERROR (Status)) {
354   	//
355     //build default
356     //
357     DEBUG((EFI_D_ERROR, "Build Hob from default\n"));
358     BuildGuidDataHob (
359       &gEfiMemoryTypeInformationGuid,
360       mDefaultMemoryTypeInformation,
361       sizeof (mDefaultMemoryTypeInformation)
362       );
363 
364   } else {
365   	//
366     // Build the GUID'd HOB for DXE from variable
367     //
368     DEBUG((EFI_D_ERROR, "Build Hob from variable \n"));
369     BuildGuidDataHob (
370       &gEfiMemoryTypeInformationGuid,
371       MemoryData,
372       DataSize
373       );
374   }
375 
376   return Status;
377 }
378 
379