1 /** @file
2 
3   Copyright (c) 2004  - 2016, 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 
233   MtrrSetAllMtrrs(&MtrrSetting);
234   //
SetDxeCacheMode(IN CONST EFI_PEI_SERVICES ** PeiServices)235   // Dump MTRR Setting
236   //
237   MtrrDebugPrintAllMtrrs ();
238 
239   return EFI_SUCCESS;
240 }
241 
242 EFI_STATUS
243 EFIAPI
244 SetDxeCacheMode (
245   IN  CONST EFI_PEI_SERVICES    **PeiServices
246   )
GetMemorySize(IN CONST EFI_PEI_SERVICES ** PeiServices,OUT UINT64 * LowMemoryLength,OUT UINT64 * HighMemoryLength)247 {
248   //
249   // This is not needed for now.
250   //
251   return EFI_SUCCESS;
252 }
253 
254 STATIC
255 EFI_STATUS
256 GetMemorySize (
257   IN  CONST EFI_PEI_SERVICES    **PeiServices,
258   OUT UINT64              *LowMemoryLength,
259   OUT UINT64              *HighMemoryLength
260   )
261 {
262   EFI_STATUS              Status;
263   EFI_PEI_HOB_POINTERS    Hob;
264 
265   *HighMemoryLength = 0;
266   *LowMemoryLength = 0x100000;
267 
268   //
269   // Get the HOB list for processing
270   //
271   Status = (*PeiServices)->GetHobList (PeiServices, (void **)&Hob.Raw);
272   if (EFI_ERROR(Status)) {
273     return Status;
274   }
275 
276   //
277   // Collect memory ranges
278   //
279   while (!END_OF_HOB_LIST (Hob)) {
280     if (Hob.Header->HobType == EFI_HOB_TYPE_RESOURCE_DESCRIPTOR) {
281       if (Hob.ResourceDescriptor->ResourceType == EFI_RESOURCE_SYSTEM_MEMORY) {
282         //
283         // Need memory above 1MB to be collected here
284         //
285         if (Hob.ResourceDescriptor->PhysicalStart >= 0x100000 &&
286             Hob.ResourceDescriptor->PhysicalStart < (EFI_PHYSICAL_ADDRESS) 0x100000000) {
287           *LowMemoryLength += (UINT64) (Hob.ResourceDescriptor->ResourceLength);
288         } else if (Hob.ResourceDescriptor->PhysicalStart >= (EFI_PHYSICAL_ADDRESS) 0x100000000) {
289           *HighMemoryLength += (UINT64) (Hob.ResourceDescriptor->ResourceLength);
290         }
291       }
292     }
293     Hob.Raw = GET_NEXT_HOB (Hob);
294   }
295 
296   return EFI_SUCCESS;
297 }
298 
299 
300 /**
301   Publish Memory Type Information.
PublishMemoryTypeInfo(void)302 
303   @param  NULL
304 
305   @retval EFI_SUCCESS    Success.
306   @retval Others         Errors have occurred.
307 **/
308 
309 EFI_STATUS
310 EFIAPI
311 PublishMemoryTypeInfo (
312   void
313   )
314 {
315   EFI_STATUS                      Status;
316   EFI_PEI_READ_ONLY_VARIABLE2_PPI *Variable;
317   UINTN                           DataSize;
318   EFI_MEMORY_TYPE_INFORMATION     MemoryData[EfiMaxMemoryType + 1];
319 
320   Status = PeiServicesLocatePpi (
321              &gEfiPeiReadOnlyVariable2PpiGuid,
322              0,
323              NULL,
324             (void **)&Variable
325              );
326   if (EFI_ERROR(Status)) {
327     DEBUG((EFI_D_ERROR, "WARNING: Locating Pei variable failed 0x%x \n", Status));
328     DEBUG((EFI_D_ERROR, "Build Hob from default\n"));
329     //
330     // Build the default GUID'd HOB for DXE
331     //
332     BuildGuidDataHob (
333       &gEfiMemoryTypeInformationGuid,
334       mDefaultMemoryTypeInformation,
335       sizeof (mDefaultMemoryTypeInformation)
336       );
337 
338     return Status;
339   }
340 
341 
342   DataSize = sizeof (MemoryData);
343 
344   //
345   // This variable is saved in BDS stage. Now read it back
346   //
347   Status = Variable->GetVariable (
348                        Variable,
349                        EFI_MEMORY_TYPE_INFORMATION_VARIABLE_NAME,
350                        &gEfiMemoryTypeInformationGuid,
351                        NULL,
352                        &DataSize,
353                        &MemoryData
354                        );
355   if (EFI_ERROR (Status)) {
356   	//
357     //build default
358     //
359     DEBUG((EFI_D_ERROR, "Build Hob from default\n"));
360     BuildGuidDataHob (
361       &gEfiMemoryTypeInformationGuid,
362       mDefaultMemoryTypeInformation,
363       sizeof (mDefaultMemoryTypeInformation)
364       );
365 
366   } else {
367   	//
368     // Build the GUID'd HOB for DXE from variable
369     //
370     DEBUG((EFI_D_ERROR, "Build Hob from variable \n"));
371     BuildGuidDataHob (
372       &gEfiMemoryTypeInformationGuid,
373       MemoryData,
374       DataSize
375       );
376   }
377 
378   return Status;
379 }
380 
381