1 /*++ 2 3 Copyright (c) 2006, Intel Corporation. All rights reserved.<BR> 4 This program and the accompanying materials 5 are licensed and made available under the terms and conditions of the BSD License 6 which accompanies this distribution. The full text of the license may be found at 7 http://opensource.org/licenses/bsd-license.php 8 9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, 10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. 11 12 Module Name: 13 Support.c 14 15 Abstract: 16 17 Revision History: 18 19 --*/ 20 #include "EfiLdr.h" 21 22 EFI_STATUS 23 EfiAddMemoryDescriptor( 24 UINTN *NoDesc, 25 EFI_MEMORY_DESCRIPTOR *Desc, 26 EFI_MEMORY_TYPE Type, 27 EFI_PHYSICAL_ADDRESS BaseAddress, 28 UINT64 NoPages, 29 UINT64 Attribute 30 ) 31 { 32 UINTN NumberOfDesc; 33 UINT64 Temp; 34 UINTN Index; 35 36 if (NoPages == 0) { 37 return EFI_SUCCESS; 38 } 39 40 // 41 // See if the new memory descriptor needs to be carved out of an existing memory descriptor 42 // 43 44 NumberOfDesc = *NoDesc; 45 for (Index = 0; Index < NumberOfDesc; Index++) { 46 47 if (Desc[Index].Type == EfiConventionalMemory) { 48 49 Temp = DivU64x32 ((BaseAddress - Desc[Index].PhysicalStart), EFI_PAGE_SIZE) + NoPages; 50 51 if ((Desc[Index].PhysicalStart < BaseAddress) && (Desc[Index].NumberOfPages >= Temp)) { 52 if (Desc[Index].NumberOfPages > Temp) { 53 Desc[*NoDesc].Type = EfiConventionalMemory; 54 Desc[*NoDesc].PhysicalStart = BaseAddress + MultU64x32 (NoPages, EFI_PAGE_SIZE); 55 Desc[*NoDesc].NumberOfPages = Desc[Index].NumberOfPages - Temp; 56 Desc[*NoDesc].VirtualStart = 0; 57 Desc[*NoDesc].Attribute = Desc[Index].Attribute; 58 *NoDesc = *NoDesc + 1; 59 } 60 Desc[Index].NumberOfPages = Temp - NoPages; 61 } 62 63 if ((Desc[Index].PhysicalStart == BaseAddress) && (Desc[Index].NumberOfPages == NoPages)) { 64 Desc[Index].Type = Type; 65 Desc[Index].Attribute = Attribute; 66 return EFI_SUCCESS; 67 } 68 69 if ((Desc[Index].PhysicalStart == BaseAddress) && (Desc[Index].NumberOfPages > NoPages)) { 70 Desc[Index].NumberOfPages -= NoPages; 71 Desc[Index].PhysicalStart += MultU64x32 (NoPages, EFI_PAGE_SIZE); 72 } 73 } 74 } 75 76 // 77 // Add the new memory descriptor 78 // 79 80 Desc[*NoDesc].Type = Type; 81 Desc[*NoDesc].PhysicalStart = BaseAddress; 82 Desc[*NoDesc].NumberOfPages = NoPages; 83 Desc[*NoDesc].VirtualStart = 0; 84 Desc[*NoDesc].Attribute = Attribute; 85 *NoDesc = *NoDesc + 1; 86 87 return EFI_SUCCESS; 88 } 89 90 UINTN 91 FindSpace ( 92 UINTN NoPages, 93 IN UINTN *NumberOfMemoryMapEntries, 94 IN EFI_MEMORY_DESCRIPTOR *EfiMemoryDescriptor, 95 EFI_MEMORY_TYPE Type, 96 UINT64 Attribute 97 ) 98 { 99 EFI_PHYSICAL_ADDRESS MaxPhysicalStart; 100 UINT64 MaxNoPages; 101 UINTN Index; 102 EFI_MEMORY_DESCRIPTOR *CurrentMemoryDescriptor; 103 104 MaxPhysicalStart = 0; 105 MaxNoPages = 0; 106 CurrentMemoryDescriptor = NULL; 107 for (Index = 0; Index < *NumberOfMemoryMapEntries; Index++) { 108 if (EfiMemoryDescriptor[Index].PhysicalStart + LShiftU64(EfiMemoryDescriptor[Index].NumberOfPages, EFI_PAGE_SHIFT) <= 0x100000) { 109 continue; 110 } 111 if ((EfiMemoryDescriptor[Index].Type == EfiConventionalMemory) && 112 (EfiMemoryDescriptor[Index].NumberOfPages >= NoPages)) { 113 if (EfiMemoryDescriptor[Index].PhysicalStart > MaxPhysicalStart) { 114 if (EfiMemoryDescriptor[Index].PhysicalStart + LShiftU64(EfiMemoryDescriptor[Index].NumberOfPages, EFI_PAGE_SHIFT) <= 0x100000000ULL) { 115 MaxPhysicalStart = EfiMemoryDescriptor[Index].PhysicalStart; 116 MaxNoPages = EfiMemoryDescriptor[Index].NumberOfPages; 117 CurrentMemoryDescriptor = &EfiMemoryDescriptor[Index]; 118 } 119 } 120 } 121 if ((EfiMemoryDescriptor[Index].Type == EfiReservedMemoryType) || 122 (EfiMemoryDescriptor[Index].Type >= EfiACPIReclaimMemory) ) { 123 continue; 124 } 125 if ((EfiMemoryDescriptor[Index].Type == EfiRuntimeServicesCode) || 126 (EfiMemoryDescriptor[Index].Type == EfiRuntimeServicesData)) { 127 break; 128 } 129 } 130 131 if (MaxPhysicalStart == 0) { 132 return 0; 133 } 134 135 if (MaxNoPages != NoPages) { 136 CurrentMemoryDescriptor->NumberOfPages = MaxNoPages - NoPages; 137 EfiMemoryDescriptor[*NumberOfMemoryMapEntries].Type = Type; 138 EfiMemoryDescriptor[*NumberOfMemoryMapEntries].PhysicalStart = MaxPhysicalStart + LShiftU64(MaxNoPages - NoPages, EFI_PAGE_SHIFT); 139 EfiMemoryDescriptor[*NumberOfMemoryMapEntries].NumberOfPages = NoPages; 140 EfiMemoryDescriptor[*NumberOfMemoryMapEntries].VirtualStart = 0; 141 EfiMemoryDescriptor[*NumberOfMemoryMapEntries].Attribute = Attribute; 142 *NumberOfMemoryMapEntries = *NumberOfMemoryMapEntries + 1; 143 } else { 144 CurrentMemoryDescriptor->Type = Type; 145 CurrentMemoryDescriptor->Attribute = Attribute; 146 } 147 148 return (UINTN)(MaxPhysicalStart + LShiftU64(MaxNoPages - NoPages, EFI_PAGE_SHIFT)); 149 } 150 151 VOID 152 GenMemoryMap ( 153 UINTN *NumberOfMemoryMapEntries, 154 EFI_MEMORY_DESCRIPTOR *EfiMemoryDescriptor, 155 BIOS_MEMORY_MAP *BiosMemoryMap 156 ) 157 { 158 UINT64 BaseAddress; 159 UINT64 Length; 160 EFI_MEMORY_TYPE Type; 161 UINTN Index; 162 UINTN Attr; 163 UINT64 Ceiling; 164 165 Ceiling = 0xFFFFFFFF; 166 for (Index = 0; Index < BiosMemoryMap->MemoryMapSize / sizeof(BIOS_MEMORY_MAP_ENTRY); Index++) { 167 168 switch (BiosMemoryMap->MemoryMapEntry[Index].Type) { 169 case (INT15_E820_AddressRangeMemory): 170 Type = EfiConventionalMemory; 171 Attr = EFI_MEMORY_WB; 172 break; 173 case (INT15_E820_AddressRangeReserved): 174 Type = EfiReservedMemoryType; 175 Attr = EFI_MEMORY_UC; 176 break; 177 case (INT15_E820_AddressRangeACPI): 178 Type = EfiACPIReclaimMemory; 179 Attr = EFI_MEMORY_WB; 180 break; 181 case (INT15_E820_AddressRangeNVS): 182 Type = EfiACPIMemoryNVS; 183 Attr = EFI_MEMORY_UC; 184 break; 185 default: 186 // We should not get here, according to ACPI 2.0 Spec. 187 // BIOS behaviour of the Int15h, E820h 188 Type = EfiReservedMemoryType; 189 Attr = EFI_MEMORY_UC; 190 break; 191 } 192 if (Type == EfiConventionalMemory) { 193 BaseAddress = BiosMemoryMap->MemoryMapEntry[Index].BaseAddress; 194 Length = BiosMemoryMap->MemoryMapEntry[Index].Length; 195 if (BaseAddress & EFI_PAGE_MASK) { 196 Length = Length + (BaseAddress & EFI_PAGE_MASK) - EFI_PAGE_SIZE; 197 BaseAddress = LShiftU64 (RShiftU64 (BaseAddress, EFI_PAGE_SHIFT) + 1, EFI_PAGE_SHIFT); 198 } 199 } else { 200 BaseAddress = BiosMemoryMap->MemoryMapEntry[Index].BaseAddress; 201 Length = BiosMemoryMap->MemoryMapEntry[Index].Length + (BaseAddress & EFI_PAGE_MASK); 202 BaseAddress = LShiftU64 (RShiftU64 (BaseAddress, EFI_PAGE_SHIFT), EFI_PAGE_SHIFT); 203 if (Length & EFI_PAGE_MASK) { 204 Length = LShiftU64 (RShiftU64 (Length, EFI_PAGE_SHIFT) + 1, EFI_PAGE_SHIFT); 205 } 206 // 207 // Update Memory Ceiling 208 // 209 if ((BaseAddress >= 0x100000) && (BaseAddress < 0x100000000ULL)) { 210 if (Ceiling > BaseAddress) { 211 Ceiling = BaseAddress; 212 } 213 } 214 } 215 EfiAddMemoryDescriptor ( 216 NumberOfMemoryMapEntries, 217 EfiMemoryDescriptor, 218 Type, 219 (EFI_PHYSICAL_ADDRESS)BaseAddress, 220 RShiftU64 (Length, EFI_PAGE_SHIFT), 221 Attr 222 ); 223 } 224 225 // 226 // Update MemoryMap according to Ceiling 227 // 228 for (Index = 0; Index < *NumberOfMemoryMapEntries; Index++) { 229 if ((EfiMemoryDescriptor[Index].Type == EfiConventionalMemory) && 230 (EfiMemoryDescriptor[Index].PhysicalStart > 0x100000) && 231 (EfiMemoryDescriptor[Index].PhysicalStart < 0x100000000ULL)) { 232 if (EfiMemoryDescriptor[Index].PhysicalStart >= Ceiling) { 233 EfiMemoryDescriptor[Index].Type = EfiReservedMemoryType; 234 } 235 } 236 } 237 } 238