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