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//
18// The protocols, PPI and GUID defintions for this module
19//
20#include <Ppi/MasterBootMode.h>
21#include <Ppi/BootInRecoveryMode.h>
22#include <Guid/MemoryTypeInformation.h>
23//
24// The Library classes this module consumes
25//
26#include <Library/ArmPlatformLib.h>
27#include <Library/DebugLib.h>
28#include <Library/HobLib.h>
29#include <Library/PeimEntryPoint.h>
30#include <Library/PeiServicesLib.h>
31#include <Library/PcdLib.h>
32
33EFI_STATUS
34EFIAPI
35MemoryPeim (
36  IN EFI_PHYSICAL_ADDRESS               UefiMemoryBase,
37  IN UINT64                             UefiMemorySize
38  );
39
40// May want to put this into a library so you only need the PCD settings if you are using the feature?
41VOID
42BuildMemoryTypeInformationHob (
43  VOID
44  )
45{
46  EFI_MEMORY_TYPE_INFORMATION   Info[10];
47
48  Info[0].Type          = EfiACPIReclaimMemory;
49  Info[0].NumberOfPages = PcdGet32 (PcdMemoryTypeEfiACPIReclaimMemory);
50  Info[1].Type          = EfiACPIMemoryNVS;
51  Info[1].NumberOfPages = PcdGet32 (PcdMemoryTypeEfiACPIMemoryNVS);
52  Info[2].Type          = EfiReservedMemoryType;
53  Info[2].NumberOfPages = PcdGet32 (PcdMemoryTypeEfiReservedMemoryType);
54  Info[3].Type          = EfiRuntimeServicesData;
55  Info[3].NumberOfPages = PcdGet32 (PcdMemoryTypeEfiRuntimeServicesData);
56  Info[4].Type          = EfiRuntimeServicesCode;
57  Info[4].NumberOfPages = PcdGet32 (PcdMemoryTypeEfiRuntimeServicesCode);
58  Info[5].Type          = EfiBootServicesCode;
59  Info[5].NumberOfPages = PcdGet32 (PcdMemoryTypeEfiBootServicesCode);
60  Info[6].Type          = EfiBootServicesData;
61  Info[6].NumberOfPages = PcdGet32 (PcdMemoryTypeEfiBootServicesData);
62  Info[7].Type          = EfiLoaderCode;
63  Info[7].NumberOfPages = PcdGet32 (PcdMemoryTypeEfiLoaderCode);
64  Info[8].Type          = EfiLoaderData;
65  Info[8].NumberOfPages = PcdGet32 (PcdMemoryTypeEfiLoaderData);
66
67  // Terminator for the list
68  Info[9].Type          = EfiMaxMemoryType;
69  Info[9].NumberOfPages = 0;
70
71  BuildGuidDataHob (&gEfiMemoryTypeInformationGuid, &Info, sizeof (Info));
72}
73
74/*++
75
76Routine Description:
77
78
79
80Arguments:
81
82  FileHandle  - Handle of the file being invoked.
83  PeiServices - Describes the list of possible PEI Services.
84
85Returns:
86
87  Status -  EFI_SUCCESS if the boot mode could be set
88
89--*/
90EFI_STATUS
91EFIAPI
92InitializeMemory (
93  IN       EFI_PEI_FILE_HANDLE  FileHandle,
94  IN CONST EFI_PEI_SERVICES     **PeiServices
95  )
96{
97  EFI_STATUS                            Status;
98  UINTN                                 SystemMemoryBase;
99  UINT64                                SystemMemoryTop;
100  UINTN                                 FdBase;
101  UINTN                                 FdTop;
102  UINTN                                 UefiMemoryBase;
103
104  DEBUG ((EFI_D_LOAD | EFI_D_INFO, "Memory Init PEIM Loaded\n"));
105
106  //
107  // Initialize the System Memory (DRAM)
108  //
109  if (!FeaturePcdGet (PcdSystemMemoryInitializeInSec)) {
110    // In case the DRAM has not been initialized by the secure firmware
111    ArmPlatformInitializeSystemMemory ();
112  }
113
114  // Ensure PcdSystemMemorySize has been set
115  ASSERT (PcdGet64 (PcdSystemMemorySize) != 0);
116  ASSERT (PcdGet64 (PcdSystemMemoryBase) < (UINT64)MAX_ADDRESS);
117
118  SystemMemoryBase = (UINTN)PcdGet64 (PcdSystemMemoryBase);
119  SystemMemoryTop = SystemMemoryBase + PcdGet64 (PcdSystemMemorySize);
120  if (SystemMemoryTop - 1 > MAX_ADDRESS) {
121    SystemMemoryTop = (UINT64)MAX_ADDRESS + 1;
122  }
123  FdBase = (UINTN)PcdGet64 (PcdFdBaseAddress);
124  FdTop = FdBase + (UINTN)PcdGet32 (PcdFdSize);
125
126  //
127  // Declare the UEFI memory to PEI
128  //
129
130  // In case the firmware has been shadowed in the System Memory
131  if ((FdBase >= SystemMemoryBase) && (FdTop <= SystemMemoryTop)) {
132    // Check if there is enough space between the top of the system memory and the top of the
133    // firmware to place the UEFI memory (for PEI & DXE phases)
134    if (SystemMemoryTop - FdTop >= FixedPcdGet32 (PcdSystemMemoryUefiRegionSize)) {
135      UefiMemoryBase = SystemMemoryTop - FixedPcdGet32 (PcdSystemMemoryUefiRegionSize);
136    } else {
137      // Check there is enough space for the UEFI memory
138      ASSERT (SystemMemoryBase + FixedPcdGet32 (PcdSystemMemoryUefiRegionSize) <= FdBase);
139
140      UefiMemoryBase = FdBase - FixedPcdGet32 (PcdSystemMemoryUefiRegionSize);
141    }
142  } else {
143    // Check the Firmware does not overlapped with the system memory
144    ASSERT ((FdBase < SystemMemoryBase) || (FdBase >= SystemMemoryTop));
145    ASSERT ((FdTop <= SystemMemoryBase) || (FdTop > SystemMemoryTop));
146
147    UefiMemoryBase = SystemMemoryTop - FixedPcdGet32 (PcdSystemMemoryUefiRegionSize);
148  }
149
150  Status = PeiServicesInstallPeiMemory (UefiMemoryBase, FixedPcdGet32 (PcdSystemMemoryUefiRegionSize));
151  ASSERT_EFI_ERROR (Status);
152
153  // Initialize MMU and Memory HOBs (Resource Descriptor HOBs)
154  Status = MemoryPeim (UefiMemoryBase, FixedPcdGet32 (PcdSystemMemoryUefiRegionSize));
155  ASSERT_EFI_ERROR (Status);
156
157  return Status;
158}
159