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 MtrrSetting
.Variables
.Mtrr
[0].Base
= (FixedPcdGet32 (PcdFlashAreaBaseAddress
) | CacheWriteProtected
);
200 MtrrSetting
.Variables
.Mtrr
[0].Mask
= ((~((UINT64
)(FixedPcdGet32 (PcdFlashAreaSize
) - 1))) & ValidMtrrAddressMask
) | MTRR_LIB_CACHE_MTRR_ENABLED
;
204 while (MaxMemoryLength
> MemOverflow
){
205 MtrrSetting
.Variables
.Mtrr
[Index
].Base
= (MemOverflow
& ValidMtrrAddressMask
) | CacheWriteBack
;
206 MemoryLength
= MaxMemoryLength
- MemOverflow
;
207 MemoryLength
= GetPowerOfTwo64 (MemoryLength
);
208 MtrrSetting
.Variables
.Mtrr
[Index
].Mask
= ((~(MemoryLength
- 1)) & ValidMtrrAddressMask
) | MTRR_LIB_CACHE_MTRR_ENABLED
;
210 MemOverflow
+= MemoryLength
;
214 MemoryLength
= LowMemoryLength
;
216 while (MaxMemoryLength
!= MemoryLength
) {
217 MemoryLengthUc
= GetPowerOfTwo64 (MaxMemoryLength
- MemoryLength
);
219 MtrrSetting
.Variables
.Mtrr
[Index
].Base
= ((MaxMemoryLength
- MemoryLengthUc
) & ValidMtrrAddressMask
) | CacheUncacheable
;
220 MtrrSetting
.Variables
.Mtrr
[Index
].Mask
= ((~(MemoryLengthUc
- 1)) & ValidMtrrAddressMask
) | MTRR_LIB_CACHE_MTRR_ENABLED
;
221 MaxMemoryLength
-= MemoryLengthUc
;
225 MemOverflow
=0x100000000;
226 while (HighMemoryLength
> 0) {
227 MtrrSetting
.Variables
.Mtrr
[Index
].Base
= (MemOverflow
& ValidMtrrAddressMask
) | CacheWriteBack
;
228 MemoryLength
= HighMemoryLength
;
229 MemoryLength
= GetPowerOfTwo64 (MemoryLength
);
231 if (MemoryLength
> MemOverflow
){
232 MemoryLength
= MemOverflow
;
235 MtrrSetting
.Variables
.Mtrr
[Index
].Mask
= ((~(MemoryLength
- 1)) & ValidMtrrAddressMask
) | MTRR_LIB_CACHE_MTRR_ENABLED
;
237 MemOverflow
+= MemoryLength
;
238 HighMemoryLength
-= MemoryLength
;
243 for (Index
= 0; Index
< MTRR_NUMBER_OF_VARIABLE_MTRR
; Index
++) {
244 if (MtrrSetting
.Variables
.Mtrr
[Index
].Base
== 0){
247 DEBUG ((EFI_D_INFO
, "Base=%lx, Mask=%lx\n",MtrrSetting
.Variables
.Mtrr
[Index
].Base
,MtrrSetting
.Variables
.Mtrr
[Index
].Mask
));
251 // set FE/E bits for IA32_MTRR_DEF_TYPE
253 MtrrSetting
.MtrrDefType
|= 3 <<10;
255 MtrrSetAllMtrrs(&MtrrSetting
);
259 MtrrDebugPrintAllMtrrs ();
267 IN CONST EFI_PEI_SERVICES
**PeiServices
271 // This is not needed for now.
279 IN CONST EFI_PEI_SERVICES
**PeiServices
,
280 OUT UINT64
*LowMemoryLength
,
281 OUT UINT64
*HighMemoryLength
285 EFI_PEI_HOB_POINTERS Hob
;
287 *HighMemoryLength
= 0;
288 *LowMemoryLength
= 0x100000;
291 // Get the HOB list for processing
293 Status
= (*PeiServices
)->GetHobList (PeiServices
, (void **)&Hob
.Raw
);
294 if (EFI_ERROR(Status
)) {
299 // Collect memory ranges
301 while (!END_OF_HOB_LIST (Hob
)) {
302 if (Hob
.Header
->HobType
== EFI_HOB_TYPE_RESOURCE_DESCRIPTOR
) {
303 if (Hob
.ResourceDescriptor
->ResourceType
== EFI_RESOURCE_SYSTEM_MEMORY
) {
305 // Need memory above 1MB to be collected here
307 if (Hob
.ResourceDescriptor
->PhysicalStart
>= 0x100000 &&
308 Hob
.ResourceDescriptor
->PhysicalStart
< (EFI_PHYSICAL_ADDRESS
) 0x100000000) {
309 *LowMemoryLength
+= (UINT64
) (Hob
.ResourceDescriptor
->ResourceLength
);
310 } else if (Hob
.ResourceDescriptor
->PhysicalStart
>= (EFI_PHYSICAL_ADDRESS
) 0x100000000) {
311 *HighMemoryLength
+= (UINT64
) (Hob
.ResourceDescriptor
->ResourceLength
);
315 Hob
.Raw
= GET_NEXT_HOB (Hob
);
323 Publish Memory Type Information.
327 @retval EFI_SUCCESS Success.
328 @retval Others Errors have occurred.
333 PublishMemoryTypeInfo (
338 EFI_PEI_READ_ONLY_VARIABLE2_PPI
*Variable
;
340 EFI_MEMORY_TYPE_INFORMATION MemoryData
[EfiMaxMemoryType
+ 1];
342 Status
= PeiServicesLocatePpi (
343 &gEfiPeiReadOnlyVariable2PpiGuid
,
348 if (EFI_ERROR(Status
)) {
349 DEBUG((EFI_D_ERROR
, "WARNING: Locating Pei variable failed 0x%x \n", Status
));
350 DEBUG((EFI_D_ERROR
, "Build Hob from default\n"));
352 // Build the default GUID'd HOB for DXE
355 &gEfiMemoryTypeInformationGuid
,
356 mDefaultMemoryTypeInformation
,
357 sizeof (mDefaultMemoryTypeInformation
)
364 DataSize
= sizeof (MemoryData
);
367 // This variable is saved in BDS stage. Now read it back
369 Status
= Variable
->GetVariable (
371 EFI_MEMORY_TYPE_INFORMATION_VARIABLE_NAME
,
372 &gEfiMemoryTypeInformationGuid
,
377 if (EFI_ERROR (Status
)) {
381 DEBUG((EFI_D_ERROR
, "Build Hob from default\n"));
383 &gEfiMemoryTypeInformationGuid
,
384 mDefaultMemoryTypeInformation
,
385 sizeof (mDefaultMemoryTypeInformation
)
390 // Build the GUID'd HOB for DXE from variable
392 DEBUG((EFI_D_ERROR
, "Build Hob from variable \n"));
394 &gEfiMemoryTypeInformationGuid
,