Home | History | Annotate | Download | only in MemoryInitPei
      1 /** @file
      2 *
      3 *  Copyright (c) 2011-2015, ARM Limited. All rights reserved.
      4 *
      5 *  This program and the accompanying materials
      6 *  are licensed and made available under the terms and conditions of the BSD License
      7 *  which accompanies this distribution.  The full text of the license may be found at
      8 *  http://opensource.org/licenses/bsd-license.php
      9 *
     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.
     12 *
     13 **/
     14 
     15 #include <PiPei.h>
     16 
     17 #include <Library/ArmPlatformLib.h>
     18 #include <Library/DebugLib.h>
     19 #include <Library/HobLib.h>
     20 #include <Library/MemoryAllocationLib.h>
     21 #include <Library/PcdLib.h>
     22 
     23 VOID
     24 BuildMemoryTypeInformationHob (
     25   VOID
     26   );
     27 
     28 STATIC
     29 VOID
     30 InitMmu (
     31   IN ARM_MEMORY_REGION_DESCRIPTOR  *MemoryTable
     32   )
     33 {
     34 
     35   VOID                          *TranslationTableBase;
     36   UINTN                         TranslationTableSize;
     37   RETURN_STATUS                 Status;
     38 
     39   //Note: Because we called PeiServicesInstallPeiMemory() before to call InitMmu() the MMU Page Table resides in
     40   //      DRAM (even at the top of DRAM as it is the first permanent memory allocation)
     41   Status = ArmConfigureMmu (MemoryTable, &TranslationTableBase, &TranslationTableSize);
     42   if (EFI_ERROR (Status)) {
     43     DEBUG ((EFI_D_ERROR, "Error: Failed to enable MMU\n"));
     44   }
     45 }
     46 
     47 /*++
     48 
     49 Routine Description:
     50 
     51 
     52 
     53 Arguments:
     54 
     55   FileHandle  - Handle of the file being invoked.
     56   PeiServices - Describes the list of possible PEI Services.
     57 
     58 Returns:
     59 
     60   Status -  EFI_SUCCESS if the boot mode could be set
     61 
     62 --*/
     63 EFI_STATUS
     64 EFIAPI
     65 MemoryPeim (
     66   IN EFI_PHYSICAL_ADDRESS               UefiMemoryBase,
     67   IN UINT64                             UefiMemorySize
     68   )
     69 {
     70   ARM_MEMORY_REGION_DESCRIPTOR *MemoryTable;
     71   EFI_RESOURCE_ATTRIBUTE_TYPE  ResourceAttributes;
     72   UINT64                       ResourceLength;
     73   EFI_PEI_HOB_POINTERS         NextHob;
     74   EFI_PHYSICAL_ADDRESS         FdTop;
     75   EFI_PHYSICAL_ADDRESS         SystemMemoryTop;
     76   EFI_PHYSICAL_ADDRESS         ResourceTop;
     77   BOOLEAN                      Found;
     78 
     79   // Get Virtual Memory Map from the Platform Library
     80   ArmPlatformGetVirtualMemoryMap (&MemoryTable);
     81 
     82   // Ensure PcdSystemMemorySize has been set
     83   ASSERT (PcdGet64 (PcdSystemMemorySize) != 0);
     84 
     85   //
     86   // Now, the permanent memory has been installed, we can call AllocatePages()
     87   //
     88   ResourceAttributes = (
     89       EFI_RESOURCE_ATTRIBUTE_PRESENT |
     90       EFI_RESOURCE_ATTRIBUTE_INITIALIZED |
     91       EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE |
     92       EFI_RESOURCE_ATTRIBUTE_WRITE_COMBINEABLE |
     93       EFI_RESOURCE_ATTRIBUTE_WRITE_THROUGH_CACHEABLE |
     94       EFI_RESOURCE_ATTRIBUTE_WRITE_BACK_CACHEABLE |
     95       EFI_RESOURCE_ATTRIBUTE_TESTED
     96   );
     97 
     98   //
     99   // Check if the resource for the main system memory has been declared
    100   //
    101   Found = FALSE;
    102   NextHob.Raw = GetHobList ();
    103   while ((NextHob.Raw = GetNextHob (EFI_HOB_TYPE_RESOURCE_DESCRIPTOR, NextHob.Raw)) != NULL) {
    104     if ((NextHob.ResourceDescriptor->ResourceType == EFI_RESOURCE_SYSTEM_MEMORY) &&
    105         (PcdGet64 (PcdSystemMemoryBase) >= NextHob.ResourceDescriptor->PhysicalStart) &&
    106         (NextHob.ResourceDescriptor->PhysicalStart + NextHob.ResourceDescriptor->ResourceLength <= PcdGet64 (PcdSystemMemoryBase) + PcdGet64 (PcdSystemMemorySize)))
    107     {
    108       Found = TRUE;
    109       break;
    110     }
    111     NextHob.Raw = GET_NEXT_HOB (NextHob);
    112   }
    113 
    114   if (!Found) {
    115     // Reserved the memory space occupied by the firmware volume
    116     BuildResourceDescriptorHob (
    117         EFI_RESOURCE_SYSTEM_MEMORY,
    118         ResourceAttributes,
    119         PcdGet64 (PcdSystemMemoryBase),
    120         PcdGet64 (PcdSystemMemorySize)
    121     );
    122   }
    123 
    124   //
    125   // Reserved the memory space occupied by the firmware volume
    126   //
    127 
    128   SystemMemoryTop = (EFI_PHYSICAL_ADDRESS)PcdGet64 (PcdSystemMemoryBase) + (EFI_PHYSICAL_ADDRESS)PcdGet64 (PcdSystemMemorySize);
    129   FdTop = (EFI_PHYSICAL_ADDRESS)PcdGet64 (PcdFdBaseAddress) + (EFI_PHYSICAL_ADDRESS)PcdGet32 (PcdFdSize);
    130 
    131   // EDK2 does not have the concept of boot firmware copied into DRAM. To avoid the DXE
    132   // core to overwrite this area we must mark the region with the attribute non-present
    133   if ((PcdGet64 (PcdFdBaseAddress) >= PcdGet64 (PcdSystemMemoryBase)) && (FdTop <= SystemMemoryTop)) {
    134     Found = FALSE;
    135 
    136     // Search for System Memory Hob that contains the firmware
    137     NextHob.Raw = GetHobList ();
    138     while ((NextHob.Raw = GetNextHob (EFI_HOB_TYPE_RESOURCE_DESCRIPTOR, NextHob.Raw)) != NULL) {
    139       if ((NextHob.ResourceDescriptor->ResourceType == EFI_RESOURCE_SYSTEM_MEMORY) &&
    140           (PcdGet64 (PcdFdBaseAddress) >= NextHob.ResourceDescriptor->PhysicalStart) &&
    141           (FdTop <= NextHob.ResourceDescriptor->PhysicalStart + NextHob.ResourceDescriptor->ResourceLength))
    142       {
    143         ResourceAttributes = NextHob.ResourceDescriptor->ResourceAttribute;
    144         ResourceLength = NextHob.ResourceDescriptor->ResourceLength;
    145         ResourceTop = NextHob.ResourceDescriptor->PhysicalStart + ResourceLength;
    146 
    147         if (PcdGet64 (PcdFdBaseAddress) == NextHob.ResourceDescriptor->PhysicalStart) {
    148           if (SystemMemoryTop == FdTop) {
    149             NextHob.ResourceDescriptor->ResourceAttribute = ResourceAttributes & ~EFI_RESOURCE_ATTRIBUTE_PRESENT;
    150           } else {
    151             // Create the System Memory HOB for the firmware with the non-present attribute
    152             BuildResourceDescriptorHob (EFI_RESOURCE_SYSTEM_MEMORY,
    153                                         ResourceAttributes & ~EFI_RESOURCE_ATTRIBUTE_PRESENT,
    154                                         PcdGet64 (PcdFdBaseAddress),
    155                                         PcdGet32 (PcdFdSize));
    156 
    157             // Top of the FD is system memory available for UEFI
    158             NextHob.ResourceDescriptor->PhysicalStart += PcdGet32(PcdFdSize);
    159             NextHob.ResourceDescriptor->ResourceLength -= PcdGet32(PcdFdSize);
    160           }
    161         } else {
    162           // Create the System Memory HOB for the firmware with the non-present attribute
    163           BuildResourceDescriptorHob (EFI_RESOURCE_SYSTEM_MEMORY,
    164                                       ResourceAttributes & ~EFI_RESOURCE_ATTRIBUTE_PRESENT,
    165                                       PcdGet64 (PcdFdBaseAddress),
    166                                       PcdGet32 (PcdFdSize));
    167 
    168           // Update the HOB
    169           NextHob.ResourceDescriptor->ResourceLength = PcdGet64 (PcdFdBaseAddress) - NextHob.ResourceDescriptor->PhysicalStart;
    170 
    171           // If there is some memory available on the top of the FD then create a HOB
    172           if (FdTop < NextHob.ResourceDescriptor->PhysicalStart + ResourceLength) {
    173             // Create the System Memory HOB for the remaining region (top of the FD)
    174             BuildResourceDescriptorHob (EFI_RESOURCE_SYSTEM_MEMORY,
    175                                         ResourceAttributes,
    176                                         FdTop,
    177                                         ResourceTop - FdTop);
    178           }
    179         }
    180         Found = TRUE;
    181         break;
    182       }
    183       NextHob.Raw = GET_NEXT_HOB (NextHob);
    184     }
    185 
    186     ASSERT(Found);
    187   }
    188 
    189   // Build Memory Allocation Hob
    190   InitMmu (MemoryTable);
    191 
    192   if (FeaturePcdGet (PcdPrePiProduceMemoryTypeInformationHob)) {
    193     // Optional feature that helps prevent EFI memory map fragmentation.
    194     BuildMemoryTypeInformationHob ();
    195   }
    196 
    197   return EFI_SUCCESS;
    198 }
    199