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