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