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