3 Copyright (c) 2004 - 2016, Intel Corporation. All rights reserved.<BR>
5 This program and the accompanying materials are licensed and made available under
6 the terms and conditions of the BSD License that accompanies this distribution.
7 The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php.
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
21 Tiano PEIM to provide the platform support functionality.
22 This file implements the Platform Memory Range PPI
26 #include "PlatformEarlyInit.h"
29 // Need min. of 48MB PEI phase
31 #define PEI_MIN_MEMORY_SIZE (6 * 0x800000)
32 #define PEI_RECOVERY_MIN_MEMORY_SIZE (6 * 0x800000)
35 // This is the memory needed for PEI to start up DXE.
37 // Over-estimating this size will lead to higher fragmentation
38 // of main memory. Under-estimation of this will cause catastrophic
39 // failure of PEI to load DXE. Generally, the failure may only be
40 // realized during capsule updates.
42 #define PRERESERVED_PEI_MEMORY ( \
43 EFI_SIZE_TO_PAGES (3 * 0x800000) /* PEI Core memory based stack */ \
46 EFI_MEMORY_TYPE_INFORMATION mDefaultMemoryTypeInformation
[] = {
47 { EfiACPIReclaimMemory
, 0x40 }, // 0x40 pages = 256k for ASL
48 { EfiACPIMemoryNVS
, 0x100 }, // 0x100 pages = 1 MB for S3, SMM, HII, etc
49 { EfiReservedMemoryType
, 0x600 }, // 48k for BIOS Reserved
50 { EfiMemoryMappedIO
, 0 },
51 { EfiMemoryMappedIOPortSpace
, 0 },
53 { EfiRuntimeServicesCode
, 0x200 },
54 { EfiRuntimeServicesData
, 0x100 },
55 { EfiLoaderCode
, 0x100 },
56 { EfiLoaderData
, 0x100 },
57 { EfiBootServicesCode
, 0x800 },
58 { EfiBootServicesData
, 0x2500},
59 { EfiConventionalMemory
, 0 },
60 { EfiUnusableMemory
, 0 },
61 { EfiMaxMemoryType
, 0 }
67 IN CONST EFI_PEI_SERVICES
**PeiServices
,
68 OUT UINT64
*LowMemoryLength
,
69 OUT UINT64
*HighMemoryLength
74 Initializes the valid address mask for MTRRs.
76 This function initializes the valid bits mask and valid address mask for MTRRs.
80 InitializeAddressMtrrMask (
85 UINT8 PhysicalAddressBits
;
86 UINT64 ValidMtrrBitsMask
;
88 AsmCpuid (0x80000000, &RegEax
, NULL
, NULL
, NULL
);
90 if (RegEax
>= 0x80000008) {
91 AsmCpuid (0x80000008, &RegEax
, NULL
, NULL
, NULL
);
93 PhysicalAddressBits
= (UINT8
) RegEax
;
95 PhysicalAddressBits
= 36;
98 ValidMtrrBitsMask
= LShiftU64 (1, PhysicalAddressBits
) - 1;
99 return (ValidMtrrBitsMask
& 0xfffffffffffff000ULL
);
105 IN CONST EFI_PEI_SERVICES
**PeiServices
109 PEI_CACHE_PPI
*CachePpi
;
111 EFI_BOOT_MODE BootMode
;
114 UINT64 MemoryLengthUc
;
115 UINT64 MaxMemoryLength
;
116 UINT64 LowMemoryLength
;
117 UINT64 HighMemoryLength
;
119 MTRR_SETTINGS MtrrSetting
;
120 UINT64 ValidMtrrAddressMask
;
125 Status
= (**PeiServices
).LocatePpi (
127 &gPeiCachePpiGuid
, // GUID
129 NULL
, // EFI_PEI_PPI_DESCRIPTOR
130 (void **)&CachePpi
// PPI
132 if (!EFI_ERROR(Status
)) {
134 // Clear the CAR Settings (Default Cache Type => UC)
136 DEBUG ((EFI_D_INFO
, "Reset cache attribute and disable CAR. \n"));
137 CachePpi
->ResetCache(
138 (EFI_PEI_SERVICES
**)PeiServices
,
145 // Variable initialization
148 HighMemoryLength
= 0;
151 Status
= (*PeiServices
)->GetBootMode (
156 ValidMtrrAddressMask
= InitializeAddressMtrrMask ();
159 // Determine memory usage
167 LowMemoryLength
= (EFI_PHYSICAL_ADDRESS
)MmPci32( 0, 0, 2, 0, 0x70);
168 LowMemoryLength
&= 0xFFF00000ULL
;
170 MaxMemoryLength
= LowMemoryLength
;
173 // Round up to nearest 256MB with high memory and 64MB w/o high memory
175 if (HighMemoryLength
!= 0 ) {
176 MemOverflow
= (LowMemoryLength
& 0x0fffffff);
177 if (MemOverflow
!= 0) {
178 MaxMemoryLength
= LowMemoryLength
+ (0x10000000 - MemOverflow
);
181 MemOverflow
= (LowMemoryLength
& 0x03ffffff);
182 if (MemOverflow
!= 0) {
183 MaxMemoryLength
= LowMemoryLength
+ (0x4000000 - MemOverflow
);
187 ZeroMem (&MtrrSetting
, sizeof(MTRR_SETTINGS
));
188 for (Index
= 0; Index
< 2; Index
++) {
189 MtrrSetting
.Fixed
.Mtrr
[Index
]=0x0606060606060606;
191 for (Index
= 2; Index
< 11; Index
++) {
192 MtrrSetting
.Fixed
.Mtrr
[Index
]=0x0505050505050505;
196 // Cache the flash area to improve the boot performance in PEI phase
199 ((MSR_IA32_MTRR_PHYSBASE_REGISTER
*) &MtrrSetting
.Variables
.Mtrr
[0].Base
)->Uint64
= FixedPcdGet32 (PcdFlashAreaBaseAddress
);
200 ((MSR_IA32_MTRR_PHYSBASE_REGISTER
*) &MtrrSetting
.Variables
.Mtrr
[0].Base
)->Bits
.Type
= CacheWriteProtected
;
201 ((MSR_IA32_MTRR_PHYSMASK_REGISTER
*) &MtrrSetting
.Variables
.Mtrr
[0].Mask
)->Uint64
= (~((UINT64
)(FixedPcdGet32 (PcdFlashAreaSize
) - 1))) & ValidMtrrAddressMask
;
202 ((MSR_IA32_MTRR_PHYSMASK_REGISTER
*) &MtrrSetting
.Variables
.Mtrr
[0].Mask
)->Bits
.V
= 1;
207 while (MaxMemoryLength
> MemOverflow
){
208 MemoryLength
= MaxMemoryLength
- MemOverflow
;
209 MemoryLength
= GetPowerOfTwo64 (MemoryLength
);
211 ((MSR_IA32_MTRR_PHYSBASE_REGISTER
*) &MtrrSetting
.Variables
.Mtrr
[Index
].Base
)->Uint64
= MemOverflow
& ValidMtrrAddressMask
;
212 ((MSR_IA32_MTRR_PHYSBASE_REGISTER
*) &MtrrSetting
.Variables
.Mtrr
[Index
].Base
)->Bits
.Type
= CacheWriteBack
;
213 ((MSR_IA32_MTRR_PHYSMASK_REGISTER
*) &MtrrSetting
.Variables
.Mtrr
[Index
].Mask
)->Uint64
= (~(MemoryLength
- 1)) & ValidMtrrAddressMask
;
214 ((MSR_IA32_MTRR_PHYSMASK_REGISTER
*) &MtrrSetting
.Variables
.Mtrr
[Index
].Mask
)->Bits
.V
= 1;
216 MemOverflow
+= MemoryLength
;
220 MemoryLength
= LowMemoryLength
;
222 while (MaxMemoryLength
!= MemoryLength
) {
223 MemoryLengthUc
= GetPowerOfTwo64 (MaxMemoryLength
- MemoryLength
);
225 ((MSR_IA32_MTRR_PHYSBASE_REGISTER
*) &MtrrSetting
.Variables
.Mtrr
[Index
].Base
)->Uint64
= (MaxMemoryLength
- MemoryLengthUc
) & ValidMtrrAddressMask
;
226 ((MSR_IA32_MTRR_PHYSBASE_REGISTER
*) &MtrrSetting
.Variables
.Mtrr
[Index
].Base
)->Bits
.Type
= CacheUncacheable
;
227 ((MSR_IA32_MTRR_PHYSMASK_REGISTER
*) &MtrrSetting
.Variables
.Mtrr
[Index
].Mask
)->Uint64
= (~(MemoryLengthUc
- 1)) & ValidMtrrAddressMask
;
228 ((MSR_IA32_MTRR_PHYSMASK_REGISTER
*) &MtrrSetting
.Variables
.Mtrr
[Index
].Mask
)->Bits
.V
= 1;
230 MaxMemoryLength
-= MemoryLengthUc
;
234 MemOverflow
=0x100000000;
235 while (HighMemoryLength
> 0) {
237 MemoryLength
= HighMemoryLength
;
238 MemoryLength
= GetPowerOfTwo64 (MemoryLength
);
239 if (MemoryLength
> MemOverflow
){
240 MemoryLength
= MemOverflow
;
243 ((MSR_IA32_MTRR_PHYSBASE_REGISTER
*) &MtrrSetting
.Variables
.Mtrr
[Index
].Base
)->Uint64
= MemOverflow
& ValidMtrrAddressMask
;
244 ((MSR_IA32_MTRR_PHYSBASE_REGISTER
*) &MtrrSetting
.Variables
.Mtrr
[Index
].Base
)->Bits
.Type
= CacheWriteBack
;
245 ((MSR_IA32_MTRR_PHYSMASK_REGISTER
*) &MtrrSetting
.Variables
.Mtrr
[Index
].Mask
)->Uint64
= (~(MemoryLength
- 1)) & ValidMtrrAddressMask
;
246 ((MSR_IA32_MTRR_PHYSMASK_REGISTER
*) &MtrrSetting
.Variables
.Mtrr
[Index
].Mask
)->Bits
.V
= 1;
248 MemOverflow
+= MemoryLength
;
249 HighMemoryLength
-= MemoryLength
;
254 for (Index
= 0; Index
< MTRR_NUMBER_OF_VARIABLE_MTRR
; Index
++) {
255 if (MtrrSetting
.Variables
.Mtrr
[Index
].Base
== 0){
258 DEBUG ((EFI_D_INFO
, "Base=%lx, Mask=%lx\n",MtrrSetting
.Variables
.Mtrr
[Index
].Base
,MtrrSetting
.Variables
.Mtrr
[Index
].Mask
));
262 // set FE/E bits for IA32_MTRR_DEF_TYPE
264 MtrrSetting
.MtrrDefType
|= 3 <<10;
266 MtrrSetAllMtrrs(&MtrrSetting
);
270 MtrrDebugPrintAllMtrrs ();
278 IN CONST EFI_PEI_SERVICES
**PeiServices
282 // This is not needed for now.
290 IN CONST EFI_PEI_SERVICES
**PeiServices
,
291 OUT UINT64
*LowMemoryLength
,
292 OUT UINT64
*HighMemoryLength
296 EFI_PEI_HOB_POINTERS Hob
;
298 *HighMemoryLength
= 0;
299 *LowMemoryLength
= 0x100000;
302 // Get the HOB list for processing
304 Status
= (*PeiServices
)->GetHobList (PeiServices
, (void **)&Hob
.Raw
);
305 if (EFI_ERROR(Status
)) {
310 // Collect memory ranges
312 while (!END_OF_HOB_LIST (Hob
)) {
313 if (Hob
.Header
->HobType
== EFI_HOB_TYPE_RESOURCE_DESCRIPTOR
) {
314 if (Hob
.ResourceDescriptor
->ResourceType
== EFI_RESOURCE_SYSTEM_MEMORY
) {
316 // Need memory above 1MB to be collected here
318 if (Hob
.ResourceDescriptor
->PhysicalStart
>= 0x100000 &&
319 Hob
.ResourceDescriptor
->PhysicalStart
< (EFI_PHYSICAL_ADDRESS
) 0x100000000) {
320 *LowMemoryLength
+= (UINT64
) (Hob
.ResourceDescriptor
->ResourceLength
);
321 } else if (Hob
.ResourceDescriptor
->PhysicalStart
>= (EFI_PHYSICAL_ADDRESS
) 0x100000000) {
322 *HighMemoryLength
+= (UINT64
) (Hob
.ResourceDescriptor
->ResourceLength
);
326 Hob
.Raw
= GET_NEXT_HOB (Hob
);
334 Publish Memory Type Information.
338 @retval EFI_SUCCESS Success.
339 @retval Others Errors have occurred.
344 PublishMemoryTypeInfo (
349 EFI_PEI_READ_ONLY_VARIABLE2_PPI
*Variable
;
351 EFI_MEMORY_TYPE_INFORMATION MemoryData
[EfiMaxMemoryType
+ 1];
353 Status
= PeiServicesLocatePpi (
354 &gEfiPeiReadOnlyVariable2PpiGuid
,
359 if (EFI_ERROR(Status
)) {
360 DEBUG((EFI_D_ERROR
, "WARNING: Locating Pei variable failed 0x%x \n", Status
));
361 DEBUG((EFI_D_ERROR
, "Build Hob from default\n"));
363 // Build the default GUID'd HOB for DXE
366 &gEfiMemoryTypeInformationGuid
,
367 mDefaultMemoryTypeInformation
,
368 sizeof (mDefaultMemoryTypeInformation
)
375 DataSize
= sizeof (MemoryData
);
378 // This variable is saved in BDS stage. Now read it back
380 Status
= Variable
->GetVariable (
382 EFI_MEMORY_TYPE_INFORMATION_VARIABLE_NAME
,
383 &gEfiMemoryTypeInformationGuid
,
388 if (EFI_ERROR (Status
)) {
392 DEBUG((EFI_D_ERROR
, "Build Hob from default\n"));
394 &gEfiMemoryTypeInformationGuid
,
395 mDefaultMemoryTypeInformation
,
396 sizeof (mDefaultMemoryTypeInformation
)
401 // Build the GUID'd HOB for DXE from variable
403 DEBUG((EFI_D_ERROR
, "Build Hob from variable \n"));
405 &gEfiMemoryTypeInformationGuid
,