MemoryInitPeiLib.c revision 6f050ad6bf16f3f2ae2f0b62e93404230de575cc
1/** @file
2*
3*  Copyright (c) 2011, 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
23VOID
24BuildMemoryTypeInformationHob (
25  VOID
26  );
27
28VOID
29InitMmu (
30  VOID
31  )
32{
33  ARM_MEMORY_REGION_DESCRIPTOR  *MemoryTable;
34  VOID                          *TranslationTableBase;
35  UINTN                         TranslationTableSize;
36  RETURN_STATUS                 Status;
37
38  // Get Virtual Memory Map from the Platform Library
39  ArmPlatformGetVirtualMemoryMap (&MemoryTable);
40
41  //Note: Because we called PeiServicesInstallPeiMemory() before to call InitMmu() the MMU Page Table resides in
42  //      DRAM (even at the top of DRAM as it is the first permanent memory allocation)
43  Status = ArmConfigureMmu (MemoryTable, &TranslationTableBase, &TranslationTableSize);
44  if (EFI_ERROR (Status)) {
45    DEBUG ((EFI_D_ERROR, "Error: Failed to enable MMU\n"));
46  }
47}
48
49/*++
50
51Routine Description:
52
53
54
55Arguments:
56
57  FileHandle  - Handle of the file being invoked.
58  PeiServices - Describes the list of possible PEI Services.
59
60Returns:
61
62  Status -  EFI_SUCCESS if the boot mode could be set
63
64--*/
65EFI_STATUS
66EFIAPI
67MemoryPeim (
68  IN EFI_PHYSICAL_ADDRESS               UefiMemoryBase,
69  IN UINT64                             UefiMemorySize
70  )
71{
72  EFI_RESOURCE_ATTRIBUTE_TYPE ResourceAttributes;
73  UINT64                      ResourceLength;
74  EFI_PEI_HOB_POINTERS        NextHob;
75  EFI_PHYSICAL_ADDRESS        FdTop;
76  EFI_PHYSICAL_ADDRESS        SystemMemoryTop;
77  EFI_PHYSICAL_ADDRESS        ResourceTop;
78  BOOLEAN                     Found;
79
80  // Ensure PcdSystemMemorySize has been set
81  ASSERT (PcdGet32 (PcdSystemMemorySize) != 0);
82
83  //
84  // Now, the permanent memory has been installed, we can call AllocatePages()
85  //
86  ResourceAttributes = (
87      EFI_RESOURCE_ATTRIBUTE_PRESENT |
88      EFI_RESOURCE_ATTRIBUTE_INITIALIZED |
89      EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE |
90      EFI_RESOURCE_ATTRIBUTE_WRITE_COMBINEABLE |
91      EFI_RESOURCE_ATTRIBUTE_WRITE_THROUGH_CACHEABLE |
92      EFI_RESOURCE_ATTRIBUTE_WRITE_BACK_CACHEABLE |
93      EFI_RESOURCE_ATTRIBUTE_TESTED
94  );
95
96  // Reserved the memory space occupied by the firmware volume
97  BuildResourceDescriptorHob (
98      EFI_RESOURCE_SYSTEM_MEMORY,
99      ResourceAttributes,
100      PcdGet32 (PcdSystemMemoryBase),
101      PcdGet32 (PcdSystemMemorySize)
102  );
103
104  SystemMemoryTop = PcdGet32 (PcdSystemMemoryBase) + PcdGet32 (PcdSystemMemorySize);
105  FdTop = PcdGet32(PcdFdBaseAddress) + PcdGet32(PcdFdSize);
106
107  // EDK2 does not have the concept of boot firmware copied into DRAM. To avoid the DXE
108  // core to overwrite this area we must mark the region with the attribute non-present
109  if ((PcdGet32 (PcdFdBaseAddress) >= PcdGet32 (PcdSystemMemoryBase)) && (FdTop <= SystemMemoryTop)) {
110    Found = FALSE;
111
112    // Search for System Memory Hob that contains the firmware
113    NextHob.Raw = GetHobList ();
114    while ((NextHob.Raw = GetNextHob (EFI_HOB_TYPE_RESOURCE_DESCRIPTOR, NextHob.Raw)) != NULL) {
115      if ((NextHob.ResourceDescriptor->ResourceType == EFI_RESOURCE_SYSTEM_MEMORY) &&
116          (PcdGet32(PcdFdBaseAddress) >= NextHob.ResourceDescriptor->PhysicalStart) &&
117          (FdTop <= NextHob.ResourceDescriptor->PhysicalStart + NextHob.ResourceDescriptor->ResourceLength))
118      {
119        ResourceAttributes = NextHob.ResourceDescriptor->ResourceAttribute;
120        ResourceLength = NextHob.ResourceDescriptor->ResourceLength;
121        ResourceTop = NextHob.ResourceDescriptor->PhysicalStart + ResourceLength;
122
123        if (PcdGet32(PcdFdBaseAddress) == NextHob.ResourceDescriptor->PhysicalStart) {
124          if (SystemMemoryTop == FdTop) {
125            NextHob.ResourceDescriptor->ResourceAttribute = ResourceAttributes & ~EFI_RESOURCE_ATTRIBUTE_PRESENT;
126          } else {
127            // Create the System Memory HOB for the firmware with the non-present attribute
128            BuildResourceDescriptorHob (EFI_RESOURCE_SYSTEM_MEMORY,
129                                        ResourceAttributes & ~EFI_RESOURCE_ATTRIBUTE_PRESENT,
130                                        PcdGet32(PcdFdBaseAddress),
131                                        PcdGet32(PcdFdSize));
132
133            // Top of the FD is system memory available for UEFI
134            NextHob.ResourceDescriptor->PhysicalStart += PcdGet32(PcdFdSize);
135            NextHob.ResourceDescriptor->ResourceLength -= PcdGet32(PcdFdSize);
136          }
137        } else {
138          // Create the System Memory HOB for the firmware with the non-present attribute
139          BuildResourceDescriptorHob (EFI_RESOURCE_SYSTEM_MEMORY,
140                                      ResourceAttributes & ~EFI_RESOURCE_ATTRIBUTE_PRESENT,
141                                      PcdGet32(PcdFdBaseAddress),
142                                      PcdGet32(PcdFdSize));
143
144          // Update the HOB
145          NextHob.ResourceDescriptor->ResourceLength = PcdGet32(PcdFdBaseAddress) - NextHob.ResourceDescriptor->PhysicalStart;
146
147          // If there is some memory available on the top of the FD then create a HOB
148          if (FdTop < NextHob.ResourceDescriptor->PhysicalStart + ResourceLength) {
149            // Create the System Memory HOB for the remaining region (top of the FD)
150            BuildResourceDescriptorHob (EFI_RESOURCE_SYSTEM_MEMORY,
151                                        ResourceAttributes,
152                                        FdTop,
153                                        ResourceTop - FdTop);
154          }
155        }
156        Found = TRUE;
157        break;
158      }
159      NextHob.Raw = GET_NEXT_HOB (NextHob);
160    }
161
162    ASSERT(Found);
163  }
164
165  // Build Memory Allocation Hob
166  InitMmu ();
167
168  if (FeaturePcdGet (PcdPrePiProduceMemoryTypeInformationHob)) {
169    // Optional feature that helps prevent EFI memory map fragmentation.
170    BuildMemoryTypeInformationHob ();
171  }
172
173  return EFI_SUCCESS;
174}
175