blob: a0c9046935d5cb25884301f6bf1840c9fd88a1c1 [file] [log] [blame]
Vishal Bhoj82c80712015-12-15 21:13:33 +05301/*++
2
3Copyright (c) 2006, Intel Corporation. All rights reserved.<BR>
4This program and the accompanying materials
5are licensed and made available under the terms and conditions of the BSD License
6which accompanies this distribution. The full text of the license may be found at
7http://opensource.org/licenses/bsd-license.php
8
9THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
11
12Module Name:
13 Support.c
14
15Abstract:
16
17Revision History:
18
19--*/
20#include "EfiLdr.h"
21
22EFI_STATUS
23EfiAddMemoryDescriptor(
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
90UINTN
91FindSpace (
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
151VOID
152GenMemoryMap (
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}