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