3 Copyright (c) 2004 - 2016, Intel Corporation. All rights reserved.<BR>
5 SPDX-License-Identifier: BSD-2-Clause-Patent
16 Tiano PEIM to provide the platform support functionality.
17 This file implements the Platform Memory Range PPI
21 #include "PlatformEarlyInit.h"
24 // Need min. of 48MB PEI phase
26 #define PEI_MIN_MEMORY_SIZE (6 * 0x800000)
27 #define PEI_RECOVERY_MIN_MEMORY_SIZE (6 * 0x800000)
30 // This is the memory needed for PEI to start up DXE.
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.
37 #define PRERESERVED_PEI_MEMORY ( \
38 EFI_SIZE_TO_PAGES (3 * 0x800000) /* PEI Core memory based stack */ \
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 },
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 }
62 IN CONST EFI_PEI_SERVICES
**PeiServices
,
63 OUT UINT64
*LowMemoryLength
,
64 OUT UINT64
*HighMemoryLength
69 Initializes the valid address mask for MTRRs.
71 This function initializes the valid bits mask and valid address mask for MTRRs.
75 InitializeAddressMtrrMask (
80 UINT8 PhysicalAddressBits
;
81 UINT64 ValidMtrrBitsMask
;
83 AsmCpuid (0x80000000, &RegEax
, NULL
, NULL
, NULL
);
85 if (RegEax
>= 0x80000008) {
86 AsmCpuid (0x80000008, &RegEax
, NULL
, NULL
, NULL
);
88 PhysicalAddressBits
= (UINT8
) RegEax
;
90 PhysicalAddressBits
= 36;
93 ValidMtrrBitsMask
= LShiftU64 (1, PhysicalAddressBits
) - 1;
94 return (ValidMtrrBitsMask
& 0xfffffffffffff000ULL
);
100 IN CONST EFI_PEI_SERVICES
**PeiServices
104 PEI_CACHE_PPI
*CachePpi
;
106 EFI_BOOT_MODE BootMode
;
109 UINT64 MemoryLengthUc
;
110 UINT64 MaxMemoryLength
;
111 UINT64 LowMemoryLength
;
112 UINT64 HighMemoryLength
;
114 MTRR_SETTINGS MtrrSetting
;
115 UINT64 ValidMtrrAddressMask
;
120 Status
= (**PeiServices
).LocatePpi (
122 &gPeiCachePpiGuid
, // GUID
124 NULL
, // EFI_PEI_PPI_DESCRIPTOR
125 (void **)&CachePpi
// PPI
127 if (!EFI_ERROR(Status
)) {
129 // Clear the CAR Settings (Default Cache Type => UC)
131 DEBUG ((EFI_D_INFO
, "Reset cache attribute and disable CAR. \n"));
132 CachePpi
->ResetCache(
133 (EFI_PEI_SERVICES
**)PeiServices
,
140 // Variable initialization
143 HighMemoryLength
= 0;
146 Status
= (*PeiServices
)->GetBootMode (
151 ValidMtrrAddressMask
= InitializeAddressMtrrMask ();
154 // Determine memory usage
162 LowMemoryLength
= (EFI_PHYSICAL_ADDRESS
)MmPci32( 0, 0, 2, 0, 0x70);
163 LowMemoryLength
&= 0xFFF00000ULL
;
165 MaxMemoryLength
= LowMemoryLength
;
168 // Round up to nearest 256MB with high memory and 64MB w/o high memory
170 if (HighMemoryLength
!= 0 ) {
171 MemOverflow
= (LowMemoryLength
& 0x0fffffff);
172 if (MemOverflow
!= 0) {
173 MaxMemoryLength
= LowMemoryLength
+ (0x10000000 - MemOverflow
);
176 MemOverflow
= (LowMemoryLength
& 0x03ffffff);
177 if (MemOverflow
!= 0) {
178 MaxMemoryLength
= LowMemoryLength
+ (0x4000000 - MemOverflow
);
182 ZeroMem (&MtrrSetting
, sizeof(MTRR_SETTINGS
));
183 for (Index
= 0; Index
< 2; Index
++) {
184 MtrrSetting
.Fixed
.Mtrr
[Index
]=0x0606060606060606;
186 for (Index
= 2; Index
< 11; Index
++) {
187 MtrrSetting
.Fixed
.Mtrr
[Index
]=0x0505050505050505;
191 // Cache the flash area to improve the boot performance in PEI phase
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;
202 while (MaxMemoryLength
> MemOverflow
){
203 MemoryLength
= MaxMemoryLength
- MemOverflow
;
204 MemoryLength
= GetPowerOfTwo64 (MemoryLength
);
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;
211 MemOverflow
+= MemoryLength
;
215 MemoryLength
= LowMemoryLength
;
217 while (MaxMemoryLength
!= MemoryLength
) {
218 MemoryLengthUc
= GetPowerOfTwo64 (MaxMemoryLength
- MemoryLength
);
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;
225 MaxMemoryLength
-= MemoryLengthUc
;
229 MemOverflow
=0x100000000;
230 while (HighMemoryLength
> 0) {
232 MemoryLength
= HighMemoryLength
;
233 MemoryLength
= GetPowerOfTwo64 (MemoryLength
);
234 if (MemoryLength
> MemOverflow
){
235 MemoryLength
= MemOverflow
;
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;
243 MemOverflow
+= MemoryLength
;
244 HighMemoryLength
-= MemoryLength
;
249 for (Index
= 0; Index
< MTRR_NUMBER_OF_VARIABLE_MTRR
; Index
++) {
250 if (MtrrSetting
.Variables
.Mtrr
[Index
].Base
== 0){
253 DEBUG ((EFI_D_INFO
, "Base=%lx, Mask=%lx\n",MtrrSetting
.Variables
.Mtrr
[Index
].Base
,MtrrSetting
.Variables
.Mtrr
[Index
].Mask
));
257 // set FE/E bits for IA32_MTRR_DEF_TYPE
259 MtrrSetting
.MtrrDefType
|= 3 <<10;
261 MtrrSetAllMtrrs(&MtrrSetting
);
265 MtrrDebugPrintAllMtrrs ();
273 IN CONST EFI_PEI_SERVICES
**PeiServices
277 // This is not needed for now.
285 IN CONST EFI_PEI_SERVICES
**PeiServices
,
286 OUT UINT64
*LowMemoryLength
,
287 OUT UINT64
*HighMemoryLength
291 EFI_PEI_HOB_POINTERS Hob
;
293 *HighMemoryLength
= 0;
294 *LowMemoryLength
= 0x100000;
297 // Get the HOB list for processing
299 Status
= (*PeiServices
)->GetHobList (PeiServices
, (void **)&Hob
.Raw
);
300 if (EFI_ERROR(Status
)) {
305 // Collect memory ranges
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
) {
311 // Need memory above 1MB to be collected here
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
);
321 Hob
.Raw
= GET_NEXT_HOB (Hob
);
329 Publish Memory Type Information.
333 @retval EFI_SUCCESS Success.
334 @retval Others Errors have occurred.
339 PublishMemoryTypeInfo (
344 EFI_PEI_READ_ONLY_VARIABLE2_PPI
*Variable
;
346 EFI_MEMORY_TYPE_INFORMATION MemoryData
[EfiMaxMemoryType
+ 1];
348 Status
= PeiServicesLocatePpi (
349 &gEfiPeiReadOnlyVariable2PpiGuid
,
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"));
358 // Build the default GUID'd HOB for DXE
361 &gEfiMemoryTypeInformationGuid
,
362 mDefaultMemoryTypeInformation
,
363 sizeof (mDefaultMemoryTypeInformation
)
370 DataSize
= sizeof (MemoryData
);
373 // This variable is saved in BDS stage. Now read it back
375 Status
= Variable
->GetVariable (
377 EFI_MEMORY_TYPE_INFORMATION_VARIABLE_NAME
,
378 &gEfiMemoryTypeInformationGuid
,
383 if (EFI_ERROR (Status
)) {
387 DEBUG((EFI_D_ERROR
, "Build Hob from default\n"));
389 &gEfiMemoryTypeInformationGuid
,
390 mDefaultMemoryTypeInformation
,
391 sizeof (mDefaultMemoryTypeInformation
)
396 // Build the GUID'd HOB for DXE from variable
398 DEBUG((EFI_D_ERROR
, "Build Hob from variable \n"));
400 &gEfiMemoryTypeInformationGuid
,