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