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