]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Core/Dxe/Gcd/Gcd.c
MdeModulePkg/Dxe/Gcd: disregard memory above MAX_ALLOC_ADDRESS
[mirror_edk2.git] / MdeModulePkg / Core / Dxe / Gcd / Gcd.c
CommitLineData
23c98c94 1/** @file\r
2 The file contains the GCD related services in the EFI Boot Services Table.\r
022c6d45 3 The GCD services are used to manage the memory and I/O regions that\r
e94a9ff7 4 are accessible to the CPU that is executing the DXE core.\r
504214c4 5\r
e037e88c 6Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>\r
cd5ebaa0 7This program and the accompanying materials\r
23c98c94 8are licensed and made available under the terms and conditions of the BSD License\r
9which accompanies this distribution. The full text of the license may be found at\r
10http://opensource.org/licenses/bsd-license.php\r
11\r
12THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
13WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
28a00297 14\r
504214c4 15**/\r
28a00297 16\r
9c4ac31c 17#include "DxeMain.h"\r
ec90508b 18#include "Gcd.h"\r
7fef06af 19#include "Mem/HeapGuard.h"\r
28a00297 20\r
21#define MINIMUM_INITIAL_MEMORY_SIZE 0x10000\r
22\r
23#define MEMORY_ATTRIBUTE_MASK (EFI_RESOURCE_ATTRIBUTE_PRESENT | \\r
24 EFI_RESOURCE_ATTRIBUTE_INITIALIZED | \\r
25 EFI_RESOURCE_ATTRIBUTE_TESTED | \\r
26 EFI_RESOURCE_ATTRIBUTE_READ_PROTECTED | \\r
27 EFI_RESOURCE_ATTRIBUTE_WRITE_PROTECTED | \\r
28 EFI_RESOURCE_ATTRIBUTE_EXECUTION_PROTECTED | \\r
6db13692 29 EFI_RESOURCE_ATTRIBUTE_READ_ONLY_PROTECTED | \\r
28a00297 30 EFI_RESOURCE_ATTRIBUTE_16_BIT_IO | \\r
31 EFI_RESOURCE_ATTRIBUTE_32_BIT_IO | \\r
a671a012
LG
32 EFI_RESOURCE_ATTRIBUTE_64_BIT_IO | \\r
33 EFI_RESOURCE_ATTRIBUTE_PERSISTENT )\r
28a00297 34\r
35#define TESTED_MEMORY_ATTRIBUTES (EFI_RESOURCE_ATTRIBUTE_PRESENT | \\r
36 EFI_RESOURCE_ATTRIBUTE_INITIALIZED | \\r
37 EFI_RESOURCE_ATTRIBUTE_TESTED )\r
38\r
39#define INITIALIZED_MEMORY_ATTRIBUTES (EFI_RESOURCE_ATTRIBUTE_PRESENT | \\r
40 EFI_RESOURCE_ATTRIBUTE_INITIALIZED )\r
41\r
42#define PRESENT_MEMORY_ATTRIBUTES (EFI_RESOURCE_ATTRIBUTE_PRESENT)\r
43\r
14dde9e9
JW
44#define EXCLUSIVE_MEMORY_ATTRIBUTES (EFI_MEMORY_UC | EFI_MEMORY_WC | \\r
45 EFI_MEMORY_WT | EFI_MEMORY_WB | \\r
46 EFI_MEMORY_WP | EFI_MEMORY_UCE)\r
47\r
48#define NONEXCLUSIVE_MEMORY_ATTRIBUTES (EFI_MEMORY_XP | EFI_MEMORY_RP | \\r
49 EFI_MEMORY_RO)\r
50\r
28a00297 51//\r
52// Module Variables\r
53//\r
54EFI_LOCK mGcdMemorySpaceLock = EFI_INITIALIZE_LOCK_VARIABLE (TPL_NOTIFY);\r
55EFI_LOCK mGcdIoSpaceLock = EFI_INITIALIZE_LOCK_VARIABLE (TPL_NOTIFY);\r
56LIST_ENTRY mGcdMemorySpaceMap = INITIALIZE_LIST_HEAD_VARIABLE (mGcdMemorySpaceMap);\r
57LIST_ENTRY mGcdIoSpaceMap = INITIALIZE_LIST_HEAD_VARIABLE (mGcdIoSpaceMap);\r
58\r
59EFI_GCD_MAP_ENTRY mGcdMemorySpaceMapEntryTemplate = {\r
60 EFI_GCD_MAP_SIGNATURE,\r
022c6d45 61 {\r
e94a9ff7 62 NULL,\r
63 NULL\r
64 },\r
28a00297 65 0,\r
66 0,\r
67 0,\r
68 0,\r
69 EfiGcdMemoryTypeNonExistent,\r
70 (EFI_GCD_IO_TYPE) 0,\r
71 NULL,\r
72 NULL\r
73};\r
74\r
75EFI_GCD_MAP_ENTRY mGcdIoSpaceMapEntryTemplate = {\r
76 EFI_GCD_MAP_SIGNATURE,\r
e94a9ff7 77 {\r
78 NULL,\r
79 NULL\r
80 },\r
28a00297 81 0,\r
82 0,\r
83 0,\r
84 0,\r
85 (EFI_GCD_MEMORY_TYPE) 0,\r
86 EfiGcdIoTypeNonExistent,\r
87 NULL,\r
88 NULL\r
89};\r
90\r
91GCD_ATTRIBUTE_CONVERSION_ENTRY mAttributeConversionTable[] = {\r
74705ca5
SZ
92 { EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE, EFI_MEMORY_UC, TRUE },\r
93 { EFI_RESOURCE_ATTRIBUTE_UNCACHED_EXPORTED, EFI_MEMORY_UCE, TRUE },\r
94 { EFI_RESOURCE_ATTRIBUTE_WRITE_COMBINEABLE, EFI_MEMORY_WC, TRUE },\r
95 { EFI_RESOURCE_ATTRIBUTE_WRITE_THROUGH_CACHEABLE, EFI_MEMORY_WT, TRUE },\r
96 { EFI_RESOURCE_ATTRIBUTE_WRITE_BACK_CACHEABLE, EFI_MEMORY_WB, TRUE },\r
97 { EFI_RESOURCE_ATTRIBUTE_READ_PROTECTABLE, EFI_MEMORY_RP, TRUE },\r
98 { EFI_RESOURCE_ATTRIBUTE_WRITE_PROTECTABLE, EFI_MEMORY_WP, TRUE },\r
99 { EFI_RESOURCE_ATTRIBUTE_EXECUTION_PROTECTABLE, EFI_MEMORY_XP, TRUE },\r
100 { EFI_RESOURCE_ATTRIBUTE_READ_ONLY_PROTECTABLE, EFI_MEMORY_RO, TRUE },\r
101 { EFI_RESOURCE_ATTRIBUTE_PRESENT, EFI_MEMORY_PRESENT, FALSE },\r
102 { EFI_RESOURCE_ATTRIBUTE_INITIALIZED, EFI_MEMORY_INITIALIZED, FALSE },\r
103 { EFI_RESOURCE_ATTRIBUTE_TESTED, EFI_MEMORY_TESTED, FALSE },\r
104 { EFI_RESOURCE_ATTRIBUTE_PERSISTABLE, EFI_MEMORY_NV, TRUE },\r
105 { EFI_RESOURCE_ATTRIBUTE_MORE_RELIABLE, EFI_MEMORY_MORE_RELIABLE, TRUE },\r
106 { 0, 0, FALSE }\r
28a00297 107};\r
108\r
f9d1f97c 109///\r
110/// Lookup table used to print GCD Memory Space Map\r
111///\r
112GLOBAL_REMOVE_IF_UNREFERENCED CONST CHAR8 *mGcdMemoryTypeNames[] = {\r
113 "NonExist ", // EfiGcdMemoryTypeNonExistent\r
114 "Reserved ", // EfiGcdMemoryTypeReserved\r
115 "SystemMem", // EfiGcdMemoryTypeSystemMemory\r
116 "MMIO ", // EfiGcdMemoryTypeMemoryMappedIo\r
35ac962b 117 "PersisMem", // EfiGcdMemoryTypePersistent\r
74705ca5 118 "MoreRelia", // EfiGcdMemoryTypeMoreReliable\r
f9d1f97c 119 "Unknown " // EfiGcdMemoryTypeMaximum\r
120};\r
121\r
122///\r
123/// Lookup table used to print GCD I/O Space Map\r
124///\r
125GLOBAL_REMOVE_IF_UNREFERENCED CONST CHAR8 *mGcdIoTypeNames[] = {\r
126 "NonExist", // EfiGcdIoTypeNonExistent\r
127 "Reserved", // EfiGcdIoTypeReserved\r
128 "I/O ", // EfiGcdIoTypeIo\r
d1102dba 129 "Unknown " // EfiGcdIoTypeMaximum\r
f9d1f97c 130};\r
131\r
132///\r
133/// Lookup table used to print GCD Allocation Types\r
134///\r
135GLOBAL_REMOVE_IF_UNREFERENCED CONST CHAR8 *mGcdAllocationTypeNames[] = {\r
136 "AnySearchBottomUp ", // EfiGcdAllocateAnySearchBottomUp\r
137 "MaxAddressSearchBottomUp ", // EfiGcdAllocateMaxAddressSearchBottomUp\r
138 "AtAddress ", // EfiGcdAllocateAddress\r
139 "AnySearchTopDown ", // EfiGcdAllocateAnySearchTopDown\r
140 "MaxAddressSearchTopDown ", // EfiGcdAllocateMaxAddressSearchTopDown\r
141 "Unknown " // EfiGcdMaxAllocateType\r
142};\r
143\r
144/**\r
145 Dump the entire contents if the GCD Memory Space Map using DEBUG() macros when\r
146 PcdDebugPrintErrorLevel has the DEBUG_GCD bit set.\r
147\r
aa927cae 148 @param InitialMap TRUE if the initial GCD Memory Map is being dumped. Otherwise, FALSE.\r
d1102dba 149\r
f9d1f97c 150**/\r
151VOID\r
152EFIAPI\r
153CoreDumpGcdMemorySpaceMap (\r
aa927cae 154 BOOLEAN InitialMap\r
f9d1f97c 155 )\r
156{\r
aa927cae 157 DEBUG_CODE (\r
158 EFI_STATUS Status;\r
159 UINTN NumberOfDescriptors;\r
160 EFI_GCD_MEMORY_SPACE_DESCRIPTOR *MemorySpaceMap;\r
161 UINTN Index;\r
d1102dba 162\r
aa927cae 163 Status = CoreGetMemorySpaceMap (&NumberOfDescriptors, &MemorySpaceMap);\r
3d267c70 164 ASSERT (Status == EFI_SUCCESS && MemorySpaceMap != NULL);\r
aa927cae 165\r
166 if (InitialMap) {\r
167 DEBUG ((DEBUG_GCD, "GCD:Initial GCD Memory Space Map\n"));\r
168 }\r
169 DEBUG ((DEBUG_GCD, "GCDMemType Range Capabilities Attributes \n"));\r
170 DEBUG ((DEBUG_GCD, "========== ================================= ================ ================\n"));\r
171 for (Index = 0; Index < NumberOfDescriptors; Index++) {\r
d1102dba 172 DEBUG ((DEBUG_GCD, "%a %016lx-%016lx %016lx %016lx%c\n",\r
aa927cae 173 mGcdMemoryTypeNames[MIN (MemorySpaceMap[Index].GcdMemoryType, EfiGcdMemoryTypeMaximum)],\r
d1102dba 174 MemorySpaceMap[Index].BaseAddress,\r
aa927cae 175 MemorySpaceMap[Index].BaseAddress + MemorySpaceMap[Index].Length - 1,\r
d1102dba 176 MemorySpaceMap[Index].Capabilities,\r
aa927cae 177 MemorySpaceMap[Index].Attributes,\r
178 MemorySpaceMap[Index].ImageHandle == NULL ? ' ' : '*'\r
179 ));\r
180 }\r
181 DEBUG ((DEBUG_GCD, "\n"));\r
182 FreePool (MemorySpaceMap);\r
183 );\r
f9d1f97c 184}\r
185\r
186/**\r
d1102dba 187 Dump the entire contents if the GCD I/O Space Map using DEBUG() macros when\r
f9d1f97c 188 PcdDebugPrintErrorLevel has the DEBUG_GCD bit set.\r
189\r
aa927cae 190 @param InitialMap TRUE if the initial GCD I/O Map is being dumped. Otherwise, FALSE.\r
d1102dba 191\r
f9d1f97c 192**/\r
193VOID\r
194EFIAPI\r
195CoreDumpGcdIoSpaceMap (\r
aa927cae 196 BOOLEAN InitialMap\r
f9d1f97c 197 )\r
198{\r
aa927cae 199 DEBUG_CODE (\r
200 EFI_STATUS Status;\r
201 UINTN NumberOfDescriptors;\r
202 EFI_GCD_IO_SPACE_DESCRIPTOR *IoSpaceMap;\r
203 UINTN Index;\r
d1102dba 204\r
aa927cae 205 Status = CoreGetIoSpaceMap (&NumberOfDescriptors, &IoSpaceMap);\r
3d267c70 206 ASSERT (Status == EFI_SUCCESS && IoSpaceMap != NULL);\r
d1102dba 207\r
aa927cae 208 if (InitialMap) {\r
209 DEBUG ((DEBUG_GCD, "GCD:Initial GCD I/O Space Map\n"));\r
d1102dba
LG
210 }\r
211\r
aa927cae 212 DEBUG ((DEBUG_GCD, "GCDIoType Range \n"));\r
213 DEBUG ((DEBUG_GCD, "========== =================================\n"));\r
214 for (Index = 0; Index < NumberOfDescriptors; Index++) {\r
d1102dba 215 DEBUG ((DEBUG_GCD, "%a %016lx-%016lx%c\n",\r
aa927cae 216 mGcdIoTypeNames[MIN (IoSpaceMap[Index].GcdIoType, EfiGcdIoTypeMaximum)],\r
d1102dba 217 IoSpaceMap[Index].BaseAddress,\r
aa927cae 218 IoSpaceMap[Index].BaseAddress + IoSpaceMap[Index].Length - 1,\r
219 IoSpaceMap[Index].ImageHandle == NULL ? ' ' : '*'\r
220 ));\r
221 }\r
222 DEBUG ((DEBUG_GCD, "\n"));\r
223 FreePool (IoSpaceMap);\r
224 );\r
f9d1f97c 225}\r
d1102dba 226\r
d12a2ecb 227/**\r
228 Validate resource descriptor HOB's attributes.\r
229\r
d1102dba 230 If Attributes includes some memory resource's settings, it should include\r
d12a2ecb 231 the corresponding capabilites also.\r
f9d1f97c 232\r
d12a2ecb 233 @param Attributes Resource descriptor HOB attributes.\r
234\r
235**/\r
236VOID\r
237CoreValidateResourceDescriptorHobAttributes (\r
238 IN UINT64 Attributes\r
239 )\r
240{\r
241 ASSERT (((Attributes & EFI_RESOURCE_ATTRIBUTE_READ_PROTECTED) == 0) ||\r
242 ((Attributes & EFI_RESOURCE_ATTRIBUTE_READ_PROTECTABLE) != 0));\r
243 ASSERT (((Attributes & EFI_RESOURCE_ATTRIBUTE_WRITE_PROTECTED) == 0) ||\r
244 ((Attributes & EFI_RESOURCE_ATTRIBUTE_WRITE_PROTECTABLE) != 0));\r
245 ASSERT (((Attributes & EFI_RESOURCE_ATTRIBUTE_EXECUTION_PROTECTED) == 0) ||\r
246 ((Attributes & EFI_RESOURCE_ATTRIBUTE_EXECUTION_PROTECTABLE) != 0));\r
6db13692
SZ
247 ASSERT (((Attributes & EFI_RESOURCE_ATTRIBUTE_READ_ONLY_PROTECTED) == 0) ||\r
248 ((Attributes & EFI_RESOURCE_ATTRIBUTE_READ_ONLY_PROTECTABLE) != 0));\r
a671a012
LG
249 ASSERT (((Attributes & EFI_RESOURCE_ATTRIBUTE_PERSISTENT) == 0) ||\r
250 ((Attributes & EFI_RESOURCE_ATTRIBUTE_PERSISTABLE) != 0));\r
d12a2ecb 251}\r
162ed594 252\r
253/**\r
254 Acquire memory lock on mGcdMemorySpaceLock.\r
255\r
256**/\r
28a00297 257VOID\r
258CoreAcquireGcdMemoryLock (\r
259 VOID\r
260 )\r
28a00297 261{\r
262 CoreAcquireLock (&mGcdMemorySpaceLock);\r
263}\r
264\r
265\r
162ed594 266\r
267/**\r
268 Release memory lock on mGcdMemorySpaceLock.\r
269\r
270**/\r
28a00297 271VOID\r
272CoreReleaseGcdMemoryLock (\r
273 VOID\r
274 )\r
28a00297 275{\r
276 CoreReleaseLock (&mGcdMemorySpaceLock);\r
277}\r
278\r
279\r
162ed594 280\r
281/**\r
282 Acquire memory lock on mGcdIoSpaceLock.\r
283\r
284**/\r
28a00297 285VOID\r
286CoreAcquireGcdIoLock (\r
287 VOID\r
288 )\r
28a00297 289{\r
290 CoreAcquireLock (&mGcdIoSpaceLock);\r
291}\r
292\r
162ed594 293\r
294/**\r
295 Release memory lock on mGcdIoSpaceLock.\r
296\r
297**/\r
28a00297 298VOID\r
299CoreReleaseGcdIoLock (\r
300 VOID\r
301 )\r
28a00297 302{\r
303 CoreReleaseLock (&mGcdIoSpaceLock);\r
304}\r
305\r
306\r
307\r
308//\r
309// GCD Initialization Worker Functions\r
310//\r
162ed594 311/**\r
312 Aligns a value to the specified boundary.\r
313\r
022c6d45 314 @param Value 64 bit value to align\r
315 @param Alignment Log base 2 of the boundary to align Value to\r
316 @param RoundUp TRUE if Value is to be rounded up to the nearest\r
317 aligned boundary. FALSE is Value is to be\r
318 rounded down to the nearest aligned boundary.\r
162ed594 319\r
320 @return A 64 bit value is the aligned to the value nearest Value with an alignment by Alignment.\r
321\r
322**/\r
28a00297 323UINT64\r
324AlignValue (\r
325 IN UINT64 Value,\r
326 IN UINTN Alignment,\r
327 IN BOOLEAN RoundUp\r
328 )\r
28a00297 329{\r
330 UINT64 AlignmentMask;\r
331\r
332 AlignmentMask = LShiftU64 (1, Alignment) - 1;\r
333 if (RoundUp) {\r
334 Value += AlignmentMask;\r
335 }\r
336 return Value & (~AlignmentMask);\r
337}\r
338\r
28a00297 339\r
162ed594 340/**\r
28a00297 341 Aligns address to the page boundary.\r
342\r
022c6d45 343 @param Value 64 bit address to align\r
28a00297 344\r
162ed594 345 @return A 64 bit value is the aligned to the value nearest Value with an alignment by Alignment.\r
28a00297 346\r
162ed594 347**/\r
28a00297 348UINT64\r
162ed594 349PageAlignAddress (\r
28a00297 350 IN UINT64 Value\r
351 )\r
162ed594 352{\r
353 return AlignValue (Value, EFI_PAGE_SHIFT, TRUE);\r
354}\r
28a00297 355\r
28a00297 356\r
162ed594 357/**\r
28a00297 358 Aligns length to the page boundary.\r
359\r
022c6d45 360 @param Value 64 bit length to align\r
28a00297 361\r
162ed594 362 @return A 64 bit value is the aligned to the value nearest Value with an alignment by Alignment.\r
28a00297 363\r
162ed594 364**/\r
162ed594 365UINT64\r
366PageAlignLength (\r
367 IN UINT64 Value\r
368 )\r
28a00297 369{\r
370 return AlignValue (Value, EFI_PAGE_SHIFT, FALSE);\r
371}\r
372\r
373//\r
374// GCD Memory Space Worker Functions\r
375//\r
162ed594 376\r
377/**\r
378 Allocate pool for two entries.\r
379\r
022c6d45 380 @param TopEntry An entry of GCD map\r
381 @param BottomEntry An entry of GCD map\r
162ed594 382\r
022c6d45 383 @retval EFI_OUT_OF_RESOURCES No enough buffer to be allocated.\r
162ed594 384 @retval EFI_SUCCESS Both entries successfully allocated.\r
385\r
386**/\r
28a00297 387EFI_STATUS\r
388CoreAllocateGcdMapEntry (\r
389 IN OUT EFI_GCD_MAP_ENTRY **TopEntry,\r
390 IN OUT EFI_GCD_MAP_ENTRY **BottomEntry\r
391 )\r
28a00297 392{\r
7fef06af
JW
393 //\r
394 // Set to mOnGuarding to TRUE before memory allocation. This will make sure\r
395 // that the entry memory is not "guarded" by HeapGuard. Otherwise it might\r
396 // cause problem when it's freed (if HeapGuard is enabled).\r
397 //\r
398 mOnGuarding = TRUE;\r
9c4ac31c 399 *TopEntry = AllocateZeroPool (sizeof (EFI_GCD_MAP_ENTRY));\r
7fef06af 400 mOnGuarding = FALSE;\r
28a00297 401 if (*TopEntry == NULL) {\r
402 return EFI_OUT_OF_RESOURCES;\r
403 }\r
404\r
7fef06af 405 mOnGuarding = TRUE;\r
9c4ac31c 406 *BottomEntry = AllocateZeroPool (sizeof (EFI_GCD_MAP_ENTRY));\r
7fef06af 407 mOnGuarding = FALSE;\r
28a00297 408 if (*BottomEntry == NULL) {\r
409 CoreFreePool (*TopEntry);\r
410 return EFI_OUT_OF_RESOURCES;\r
411 }\r
412\r
413 return EFI_SUCCESS;\r
414}\r
415\r
162ed594 416\r
417/**\r
418 Internal function. Inserts a new descriptor into a sorted list\r
419\r
022c6d45 420 @param Link The linked list to insert the range BaseAddress\r
421 and Length into\r
422 @param Entry A pointer to the entry that is inserted\r
423 @param BaseAddress The base address of the new range\r
424 @param Length The length of the new range in bytes\r
425 @param TopEntry Top pad entry to insert if needed.\r
426 @param BottomEntry Bottom pad entry to insert if needed.\r
162ed594 427\r
428 @retval EFI_SUCCESS The new range was inserted into the linked list\r
429\r
430**/\r
28a00297 431EFI_STATUS\r
432CoreInsertGcdMapEntry (\r
433 IN LIST_ENTRY *Link,\r
434 IN EFI_GCD_MAP_ENTRY *Entry,\r
435 IN EFI_PHYSICAL_ADDRESS BaseAddress,\r
436 IN UINT64 Length,\r
437 IN EFI_GCD_MAP_ENTRY *TopEntry,\r
438 IN EFI_GCD_MAP_ENTRY *BottomEntry\r
439 )\r
28a00297 440{\r
441 ASSERT (Length != 0);\r
28a00297 442\r
443 if (BaseAddress > Entry->BaseAddress) {\r
f75316c3 444 ASSERT (BottomEntry->Signature == 0);\r
445\r
28a00297 446 CopyMem (BottomEntry, Entry, sizeof (EFI_GCD_MAP_ENTRY));\r
447 Entry->BaseAddress = BaseAddress;\r
448 BottomEntry->EndAddress = BaseAddress - 1;\r
449 InsertTailList (Link, &BottomEntry->Link);\r
022c6d45 450 }\r
28a00297 451\r
452 if ((BaseAddress + Length - 1) < Entry->EndAddress) {\r
f75316c3 453 ASSERT (TopEntry->Signature == 0);\r
454\r
28a00297 455 CopyMem (TopEntry, Entry, sizeof (EFI_GCD_MAP_ENTRY));\r
456 TopEntry->BaseAddress = BaseAddress + Length;\r
457 Entry->EndAddress = BaseAddress + Length - 1;\r
458 InsertHeadList (Link, &TopEntry->Link);\r
459 }\r
460\r
461 return EFI_SUCCESS;\r
462}\r
463\r
162ed594 464\r
465/**\r
e94a9ff7 466 Merge the Gcd region specified by Link and its adjacent entry.\r
162ed594 467\r
022c6d45 468 @param Link Specify the entry to be merged (with its\r
469 adjacent entry).\r
470 @param Forward Direction (forward or backward).\r
471 @param Map Boundary.\r
162ed594 472\r
022c6d45 473 @retval EFI_SUCCESS Successfully returned.\r
162ed594 474 @retval EFI_UNSUPPORTED These adjacent regions could not merge.\r
475\r
476**/\r
28a00297 477EFI_STATUS\r
478CoreMergeGcdMapEntry (\r
479 IN LIST_ENTRY *Link,\r
480 IN BOOLEAN Forward,\r
481 IN LIST_ENTRY *Map\r
482 )\r
28a00297 483{\r
484 LIST_ENTRY *AdjacentLink;\r
485 EFI_GCD_MAP_ENTRY *Entry;\r
486 EFI_GCD_MAP_ENTRY *AdjacentEntry;\r
487\r
488 //\r
489 // Get adjacent entry\r
490 //\r
491 if (Forward) {\r
492 AdjacentLink = Link->ForwardLink;\r
493 } else {\r
494 AdjacentLink = Link->BackLink;\r
495 }\r
496\r
497 //\r
498 // If AdjacentLink is the head of the list, then no merge can be performed\r
499 //\r
500 if (AdjacentLink == Map) {\r
501 return EFI_SUCCESS;\r
502 }\r
503\r
504 Entry = CR (Link, EFI_GCD_MAP_ENTRY, Link, EFI_GCD_MAP_SIGNATURE);\r
505 AdjacentEntry = CR (AdjacentLink, EFI_GCD_MAP_ENTRY, Link, EFI_GCD_MAP_SIGNATURE);\r
506\r
507 if (Entry->Capabilities != AdjacentEntry->Capabilities) {\r
508 return EFI_UNSUPPORTED;\r
509 }\r
510 if (Entry->Attributes != AdjacentEntry->Attributes) {\r
511 return EFI_UNSUPPORTED;\r
512 }\r
513 if (Entry->GcdMemoryType != AdjacentEntry->GcdMemoryType) {\r
514 return EFI_UNSUPPORTED;\r
515 }\r
516 if (Entry->GcdIoType != AdjacentEntry->GcdIoType) {\r
517 return EFI_UNSUPPORTED;\r
518 }\r
519 if (Entry->ImageHandle != AdjacentEntry->ImageHandle) {\r
520 return EFI_UNSUPPORTED;\r
521 }\r
522 if (Entry->DeviceHandle != AdjacentEntry->DeviceHandle) {\r
523 return EFI_UNSUPPORTED;\r
524 }\r
525\r
526 if (Forward) {\r
527 Entry->EndAddress = AdjacentEntry->EndAddress;\r
528 } else {\r
529 Entry->BaseAddress = AdjacentEntry->BaseAddress;\r
530 }\r
531 RemoveEntryList (AdjacentLink);\r
532 CoreFreePool (AdjacentEntry);\r
533\r
534 return EFI_SUCCESS;\r
535}\r
536\r
162ed594 537\r
538/**\r
539 Merge adjacent entries on total chain.\r
540\r
022c6d45 541 @param TopEntry Top entry of GCD map.\r
542 @param BottomEntry Bottom entry of GCD map.\r
543 @param StartLink Start link of the list for this loop.\r
544 @param EndLink End link of the list for this loop.\r
545 @param Map Boundary.\r
162ed594 546\r
547 @retval EFI_SUCCESS GCD map successfully cleaned up.\r
548\r
549**/\r
28a00297 550EFI_STATUS\r
551CoreCleanupGcdMapEntry (\r
552 IN EFI_GCD_MAP_ENTRY *TopEntry,\r
553 IN EFI_GCD_MAP_ENTRY *BottomEntry,\r
554 IN LIST_ENTRY *StartLink,\r
555 IN LIST_ENTRY *EndLink,\r
556 IN LIST_ENTRY *Map\r
557 )\r
28a00297 558{\r
559 LIST_ENTRY *Link;\r
560\r
561 if (TopEntry->Signature == 0) {\r
562 CoreFreePool (TopEntry);\r
563 }\r
564 if (BottomEntry->Signature == 0) {\r
565 CoreFreePool (BottomEntry);\r
566 }\r
567\r
568 Link = StartLink;\r
569 while (Link != EndLink->ForwardLink) {\r
570 CoreMergeGcdMapEntry (Link, FALSE, Map);\r
571 Link = Link->ForwardLink;\r
572 }\r
573 CoreMergeGcdMapEntry (EndLink, TRUE, Map);\r
574\r
575 return EFI_SUCCESS;\r
576}\r
577\r
162ed594 578\r
579/**\r
580 Search a segment of memory space in GCD map. The result is a range of GCD entry list.\r
581\r
022c6d45 582 @param BaseAddress The start address of the segment.\r
583 @param Length The length of the segment.\r
584 @param StartLink The first GCD entry involves this segment of\r
585 memory space.\r
586 @param EndLink The first GCD entry involves this segment of\r
587 memory space.\r
588 @param Map Points to the start entry to search.\r
162ed594 589\r
022c6d45 590 @retval EFI_SUCCESS Successfully found the entry.\r
162ed594 591 @retval EFI_NOT_FOUND Not found.\r
592\r
593**/\r
28a00297 594EFI_STATUS\r
595CoreSearchGcdMapEntry (\r
596 IN EFI_PHYSICAL_ADDRESS BaseAddress,\r
597 IN UINT64 Length,\r
598 OUT LIST_ENTRY **StartLink,\r
599 OUT LIST_ENTRY **EndLink,\r
600 IN LIST_ENTRY *Map\r
601 )\r
28a00297 602{\r
603 LIST_ENTRY *Link;\r
604 EFI_GCD_MAP_ENTRY *Entry;\r
605\r
606 ASSERT (Length != 0);\r
607\r
608 *StartLink = NULL;\r
609 *EndLink = NULL;\r
610\r
611 Link = Map->ForwardLink;\r
612 while (Link != Map) {\r
613 Entry = CR (Link, EFI_GCD_MAP_ENTRY, Link, EFI_GCD_MAP_SIGNATURE);\r
614 if (BaseAddress >= Entry->BaseAddress && BaseAddress <= Entry->EndAddress) {\r
615 *StartLink = Link;\r
616 }\r
617 if (*StartLink != NULL) {\r
022c6d45 618 if ((BaseAddress + Length - 1) >= Entry->BaseAddress &&\r
28a00297 619 (BaseAddress + Length - 1) <= Entry->EndAddress ) {\r
620 *EndLink = Link;\r
621 return EFI_SUCCESS;\r
622 }\r
623 }\r
624 Link = Link->ForwardLink;\r
625 }\r
e94a9ff7 626\r
28a00297 627 return EFI_NOT_FOUND;\r
628}\r
629\r
28a00297 630\r
162ed594 631/**\r
28a00297 632 Count the amount of GCD map entries.\r
633\r
022c6d45 634 @param Map Points to the start entry to do the count loop.\r
28a00297 635\r
162ed594 636 @return The count.\r
28a00297 637\r
162ed594 638**/\r
162ed594 639UINTN\r
640CoreCountGcdMapEntry (\r
641 IN LIST_ENTRY *Map\r
642 )\r
28a00297 643{\r
644 UINTN Count;\r
645 LIST_ENTRY *Link;\r
646\r
647 Count = 0;\r
648 Link = Map->ForwardLink;\r
649 while (Link != Map) {\r
650 Count++;\r
651 Link = Link->ForwardLink;\r
652 }\r
022c6d45 653\r
28a00297 654 return Count;\r
655}\r
656\r
657\r
28a00297 658\r
162ed594 659/**\r
28a00297 660 Return the memory attribute specified by Attributes\r
661\r
022c6d45 662 @param Attributes A num with some attribute bits on.\r
28a00297 663\r
162ed594 664 @return The enum value of memory attribute.\r
28a00297 665\r
162ed594 666**/\r
162ed594 667UINT64\r
668ConverToCpuArchAttributes (\r
669 UINT64 Attributes\r
23c98c94 670 )\r
28a00297 671{\r
14dde9e9 672 UINT64 CpuArchAttributes;\r
28a00297 673\r
14dde9e9 674 CpuArchAttributes = Attributes & NONEXCLUSIVE_MEMORY_ATTRIBUTES;\r
28a00297 675\r
14dde9e9
JW
676 if ( (Attributes & EFI_MEMORY_UC) == EFI_MEMORY_UC) {\r
677 CpuArchAttributes |= EFI_MEMORY_UC;\r
678 } else if ( (Attributes & EFI_MEMORY_WC ) == EFI_MEMORY_WC) {\r
679 CpuArchAttributes |= EFI_MEMORY_WC;\r
680 } else if ( (Attributes & EFI_MEMORY_WT ) == EFI_MEMORY_WT) {\r
681 CpuArchAttributes |= EFI_MEMORY_WT;\r
682 } else if ( (Attributes & EFI_MEMORY_WB) == EFI_MEMORY_WB) {\r
683 CpuArchAttributes |= EFI_MEMORY_WB;\r
684 } else if ( (Attributes & EFI_MEMORY_UCE) == EFI_MEMORY_UCE) {\r
685 CpuArchAttributes |= EFI_MEMORY_UCE;\r
686 } else if ( (Attributes & EFI_MEMORY_WP) == EFI_MEMORY_WP) {\r
687 CpuArchAttributes |= EFI_MEMORY_WP;\r
28a00297 688 }\r
689\r
14dde9e9 690 return CpuArchAttributes;\r
28a00297 691}\r
692\r
162ed594 693\r
694/**\r
695 Do operation on a segment of memory space specified (add, free, remove, change attribute ...).\r
696\r
022c6d45 697 @param Operation The type of the operation\r
698 @param GcdMemoryType Additional information for the operation\r
699 @param GcdIoType Additional information for the operation\r
700 @param BaseAddress Start address of the segment\r
701 @param Length length of the segment\r
702 @param Capabilities The alterable attributes of a newly added entry\r
703 @param Attributes The attributes needs to be set\r
704\r
705 @retval EFI_INVALID_PARAMETER Length is 0 or address (length) not aligned when\r
706 setting attribute.\r
707 @retval EFI_SUCCESS Action successfully done.\r
708 @retval EFI_UNSUPPORTED Could not find the proper descriptor on this\r
709 segment or set an upsupported attribute.\r
710 @retval EFI_ACCESS_DENIED Operate on an space non-exist or is used for an\r
711 image.\r
712 @retval EFI_NOT_FOUND Free a non-using space or remove a non-exist\r
713 space, and so on.\r
162ed594 714 @retval EFI_OUT_OF_RESOURCES No buffer could be allocated.\r
fc8ff20f 715 @retval EFI_NOT_AVAILABLE_YET The attributes cannot be set because CPU architectural protocol\r
716 is not available yet.\r
162ed594 717**/\r
28a00297 718EFI_STATUS\r
719CoreConvertSpace (\r
720 IN UINTN Operation,\r
721 IN EFI_GCD_MEMORY_TYPE GcdMemoryType,\r
722 IN EFI_GCD_IO_TYPE GcdIoType,\r
723 IN EFI_PHYSICAL_ADDRESS BaseAddress,\r
724 IN UINT64 Length,\r
725 IN UINT64 Capabilities,\r
726 IN UINT64 Attributes\r
727 )\r
28a00297 728{\r
729 EFI_STATUS Status;\r
730 LIST_ENTRY *Map;\r
731 LIST_ENTRY *Link;\r
732 EFI_GCD_MAP_ENTRY *Entry;\r
733 EFI_GCD_MAP_ENTRY *TopEntry;\r
734 EFI_GCD_MAP_ENTRY *BottomEntry;\r
735 LIST_ENTRY *StartLink;\r
736 LIST_ENTRY *EndLink;\r
f9d1f97c 737 UINT64 CpuArchAttributes;\r
28a00297 738\r
739 if (Length == 0) {\r
aa927cae 740 DEBUG ((DEBUG_GCD, " Status = %r\n", EFI_INVALID_PARAMETER));\r
28a00297 741 return EFI_INVALID_PARAMETER;\r
742 }\r
743\r
744 Map = NULL;\r
71f68914 745 if ((Operation & GCD_MEMORY_SPACE_OPERATION) != 0) {\r
28a00297 746 CoreAcquireGcdMemoryLock ();\r
747 Map = &mGcdMemorySpaceMap;\r
fbbb4211 748 } else if ((Operation & GCD_IO_SPACE_OPERATION) != 0) {\r
28a00297 749 CoreAcquireGcdIoLock ();\r
750 Map = &mGcdIoSpaceMap;\r
fbbb4211 751 } else {\r
752 ASSERT (FALSE);\r
28a00297 753 }\r
754\r
755 //\r
756 // Search for the list of descriptors that cover the range BaseAddress to BaseAddress+Length\r
757 //\r
758 Status = CoreSearchGcdMapEntry (BaseAddress, Length, &StartLink, &EndLink, Map);\r
759 if (EFI_ERROR (Status)) {\r
760 Status = EFI_UNSUPPORTED;\r
761\r
762 goto Done;\r
763 }\r
d2fbaaab 764 ASSERT (StartLink != NULL && EndLink != NULL);\r
28a00297 765\r
766 //\r
767 // Verify that the list of descriptors are unallocated non-existent memory.\r
768 //\r
769 Link = StartLink;\r
770 while (Link != EndLink->ForwardLink) {\r
771 Entry = CR (Link, EFI_GCD_MAP_ENTRY, Link, EFI_GCD_MAP_SIGNATURE);\r
772 switch (Operation) {\r
773 //\r
774 // Add operations\r
775 //\r
776 case GCD_ADD_MEMORY_OPERATION:\r
777 if (Entry->GcdMemoryType != EfiGcdMemoryTypeNonExistent ||\r
778 Entry->ImageHandle != NULL ) {\r
779 Status = EFI_ACCESS_DENIED;\r
780 goto Done;\r
781 }\r
782 break;\r
783 case GCD_ADD_IO_OPERATION:\r
784 if (Entry->GcdIoType != EfiGcdIoTypeNonExistent ||\r
785 Entry->ImageHandle != NULL ) {\r
786 Status = EFI_ACCESS_DENIED;\r
787 goto Done;\r
788 }\r
789 break;\r
790 //\r
791 // Free operations\r
792 //\r
793 case GCD_FREE_MEMORY_OPERATION:\r
794 case GCD_FREE_IO_OPERATION:\r
795 if (Entry->ImageHandle == NULL) {\r
796 Status = EFI_NOT_FOUND;\r
797 goto Done;\r
798 }\r
799 break;\r
800 //\r
801 // Remove operations\r
802 //\r
803 case GCD_REMOVE_MEMORY_OPERATION:\r
804 if (Entry->GcdMemoryType == EfiGcdMemoryTypeNonExistent) {\r
805 Status = EFI_NOT_FOUND;\r
806 goto Done;\r
807 }\r
808 if (Entry->ImageHandle != NULL) {\r
809 Status = EFI_ACCESS_DENIED;\r
810 goto Done;\r
811 }\r
812 break;\r
813 case GCD_REMOVE_IO_OPERATION:\r
814 if (Entry->GcdIoType == EfiGcdIoTypeNonExistent) {\r
815 Status = EFI_NOT_FOUND;\r
816 goto Done;\r
817 }\r
818 if (Entry->ImageHandle != NULL) {\r
819 Status = EFI_ACCESS_DENIED;\r
820 goto Done;\r
821 }\r
822 break;\r
823 //\r
771ee501 824 // Set attributes operation\r
28a00297 825 //\r
826 case GCD_SET_ATTRIBUTES_MEMORY_OPERATION:\r
71f68914 827 if ((Attributes & EFI_MEMORY_RUNTIME) != 0) {\r
28a00297 828 if ((BaseAddress & EFI_PAGE_MASK) != 0 || (Length & EFI_PAGE_MASK) != 0) {\r
829 Status = EFI_INVALID_PARAMETER;\r
28a00297 830 goto Done;\r
831 }\r
832 }\r
833 if ((Entry->Capabilities & Attributes) != Attributes) {\r
834 Status = EFI_UNSUPPORTED;\r
835 goto Done;\r
836 }\r
837 break;\r
736a692e
HT
838 //\r
839 // Set capabilities operation\r
840 //\r
841 case GCD_SET_CAPABILITIES_MEMORY_OPERATION:\r
842 if ((BaseAddress & EFI_PAGE_MASK) != 0 || (Length & EFI_PAGE_MASK) != 0) {\r
843 Status = EFI_INVALID_PARAMETER;\r
844\r
845 goto Done;\r
771ee501 846 }\r
736a692e 847 //\r
771ee501 848 // Current attributes must still be supported with new capabilities\r
736a692e
HT
849 //\r
850 if ((Capabilities & Entry->Attributes) != Entry->Attributes) {\r
851 Status = EFI_UNSUPPORTED;\r
852 goto Done;\r
853 }\r
771ee501 854 break;\r
28a00297 855 }\r
856 Link = Link->ForwardLink;\r
857 }\r
858\r
859 //\r
860 // Allocate work space to perform this operation\r
861 //\r
862 Status = CoreAllocateGcdMapEntry (&TopEntry, &BottomEntry);\r
863 if (EFI_ERROR (Status)) {\r
864 Status = EFI_OUT_OF_RESOURCES;\r
865 goto Done;\r
866 }\r
d2fbaaab 867 ASSERT (TopEntry != NULL && BottomEntry != NULL);\r
28a00297 868\r
e037e88c
SZ
869 //\r
870 // Initialize CpuArchAttributes to suppress incorrect compiler/analyzer warnings.\r
871 //\r
872 CpuArchAttributes = 0;\r
28a00297 873 if (Operation == GCD_SET_ATTRIBUTES_MEMORY_OPERATION) {\r
874 //\r
875 // Call CPU Arch Protocol to attempt to set attributes on the range\r
876 //\r
877 CpuArchAttributes = ConverToCpuArchAttributes (Attributes);\r
0c9f2cb1 878 //\r
d1102dba 879 // CPU arch attributes include page attributes and cache attributes.\r
0c9f2cb1
KM
880 // Only page attributes supports to be cleared, but not cache attributes.\r
881 // Caller is expected to use GetMemorySpaceDescriptor() to get the current\r
882 // attributes, AND/OR attributes, and then calls SetMemorySpaceAttributes()\r
883 // to set the new attributes.\r
884 // So 0 CPU arch attributes should not happen as memory should always have\r
d1102dba 885 // a cache attribute (no matter UC or WB, etc).\r
0c9f2cb1
KM
886 //\r
887 // Here, 0 CPU arch attributes will be filtered to be compatible with the\r
888 // case that caller just calls SetMemorySpaceAttributes() with none CPU\r
889 // arch attributes (for example, RUNTIME) as the purpose of the case is not\r
890 // to clear CPU arch attributes.\r
891 //\r
892 if (CpuArchAttributes != 0) {\r
fc8ff20f 893 if (gCpu == NULL) {\r
894 Status = EFI_NOT_AVAILABLE_YET;\r
895 } else {\r
f9d1f97c 896 Status = gCpu->SetMemoryAttributes (\r
897 gCpu,\r
898 BaseAddress,\r
899 Length,\r
900 CpuArchAttributes\r
901 );\r
fc8ff20f 902 }\r
903 if (EFI_ERROR (Status)) {\r
904 CoreFreePool (TopEntry);\r
905 CoreFreePool (BottomEntry);\r
906 goto Done;\r
28a00297 907 }\r
908 }\r
28a00297 909 }\r
910\r
911 //\r
912 // Convert/Insert the list of descriptors from StartLink to EndLink\r
913 //\r
914 Link = StartLink;\r
915 while (Link != EndLink->ForwardLink) {\r
916 Entry = CR (Link, EFI_GCD_MAP_ENTRY, Link, EFI_GCD_MAP_SIGNATURE);\r
917 CoreInsertGcdMapEntry (Link, Entry, BaseAddress, Length, TopEntry, BottomEntry);\r
918 switch (Operation) {\r
919 //\r
920 // Add operations\r
921 //\r
922 case GCD_ADD_MEMORY_OPERATION:\r
923 Entry->GcdMemoryType = GcdMemoryType;\r
924 if (GcdMemoryType == EfiGcdMemoryTypeMemoryMappedIo) {\r
925 Entry->Capabilities = Capabilities | EFI_MEMORY_RUNTIME | EFI_MEMORY_PORT_IO;\r
926 } else {\r
927 Entry->Capabilities = Capabilities | EFI_MEMORY_RUNTIME;\r
928 }\r
929 break;\r
930 case GCD_ADD_IO_OPERATION:\r
931 Entry->GcdIoType = GcdIoType;\r
932 break;\r
933 //\r
934 // Free operations\r
935 //\r
936 case GCD_FREE_MEMORY_OPERATION:\r
937 case GCD_FREE_IO_OPERATION:\r
938 Entry->ImageHandle = NULL;\r
939 Entry->DeviceHandle = NULL;\r
940 break;\r
941 //\r
942 // Remove operations\r
943 //\r
944 case GCD_REMOVE_MEMORY_OPERATION:\r
945 Entry->GcdMemoryType = EfiGcdMemoryTypeNonExistent;\r
946 Entry->Capabilities = 0;\r
947 break;\r
948 case GCD_REMOVE_IO_OPERATION:\r
949 Entry->GcdIoType = EfiGcdIoTypeNonExistent;\r
950 break;\r
951 //\r
771ee501 952 // Set attributes operation\r
28a00297 953 //\r
954 case GCD_SET_ATTRIBUTES_MEMORY_OPERATION:\r
0c9f2cb1
KM
955 if (CpuArchAttributes == 0) {\r
956 //\r
957 // Keep original CPU arch attributes when caller just calls\r
958 // SetMemorySpaceAttributes() with none CPU arch attributes (for example, RUNTIME).\r
959 //\r
960 Attributes |= (Entry->Attributes & (EXCLUSIVE_MEMORY_ATTRIBUTES | NONEXCLUSIVE_MEMORY_ATTRIBUTES));\r
961 }\r
28a00297 962 Entry->Attributes = Attributes;\r
963 break;\r
771ee501
EC
964 //\r
965 // Set capabilities operation\r
966 //\r
736a692e
HT
967 case GCD_SET_CAPABILITIES_MEMORY_OPERATION:\r
968 Entry->Capabilities = Capabilities;\r
771ee501 969 break;\r
28a00297 970 }\r
971 Link = Link->ForwardLink;\r
972 }\r
973\r
974 //\r
975 // Cleanup\r
976 //\r
977 Status = CoreCleanupGcdMapEntry (TopEntry, BottomEntry, StartLink, EndLink, Map);\r
978\r
979Done:\r
aa927cae 980 DEBUG ((DEBUG_GCD, " Status = %r\n", Status));\r
f9d1f97c 981\r
71f68914 982 if ((Operation & GCD_MEMORY_SPACE_OPERATION) != 0) {\r
28a00297 983 CoreReleaseGcdMemoryLock ();\r
aa927cae 984 CoreDumpGcdMemorySpaceMap (FALSE);\r
28a00297 985 }\r
71f68914 986 if ((Operation & GCD_IO_SPACE_OPERATION) != 0) {\r
28a00297 987 CoreReleaseGcdIoLock ();\r
aa927cae 988 CoreDumpGcdIoSpaceMap (FALSE);\r
28a00297 989 }\r
990\r
991 return Status;\r
992}\r
993\r
162ed594 994\r
995/**\r
996 Check whether an entry could be used to allocate space.\r
997\r
022c6d45 998 @param Operation Allocate memory or IO\r
999 @param Entry The entry to be tested\r
1000 @param GcdMemoryType The desired memory type\r
1001 @param GcdIoType The desired IO type\r
162ed594 1002\r
022c6d45 1003 @retval EFI_NOT_FOUND The memory type does not match or there's an\r
1004 image handle on the entry.\r
1005 @retval EFI_UNSUPPORTED The operation unsupported.\r
1006 @retval EFI_SUCCESS It's ok for this entry to be used to allocate\r
162ed594 1007 space.\r
1008\r
1009**/\r
28a00297 1010EFI_STATUS\r
1011CoreAllocateSpaceCheckEntry (\r
1012 IN UINTN Operation,\r
1013 IN EFI_GCD_MAP_ENTRY *Entry,\r
1014 IN EFI_GCD_MEMORY_TYPE GcdMemoryType,\r
1015 IN EFI_GCD_IO_TYPE GcdIoType\r
1016 )\r
28a00297 1017{\r
1018 if (Entry->ImageHandle != NULL) {\r
1019 return EFI_NOT_FOUND;\r
1020 }\r
1021 switch (Operation) {\r
1022 case GCD_ALLOCATE_MEMORY_OPERATION:\r
1023 if (Entry->GcdMemoryType != GcdMemoryType) {\r
1024 return EFI_NOT_FOUND;\r
1025 }\r
1026 break;\r
1027 case GCD_ALLOCATE_IO_OPERATION:\r
1028 if (Entry->GcdIoType != GcdIoType) {\r
1029 return EFI_NOT_FOUND;\r
1030 }\r
1031 break;\r
1032 default:\r
1033 return EFI_UNSUPPORTED;\r
1034 }\r
1035 return EFI_SUCCESS;\r
1036}\r
1037\r
162ed594 1038\r
1039/**\r
1040 Allocate space on specified address and length.\r
1041\r
022c6d45 1042 @param Operation The type of operation (memory or IO)\r
1043 @param GcdAllocateType The type of allocate operation\r
1044 @param GcdMemoryType The desired memory type\r
1045 @param GcdIoType The desired IO type\r
1046 @param Alignment Align with 2^Alignment\r
1047 @param Length Length to allocate\r
1048 @param BaseAddress Base address to allocate\r
1049 @param ImageHandle The image handle consume the allocated space.\r
1050 @param DeviceHandle The device handle consume the allocated space.\r
1051\r
1052 @retval EFI_INVALID_PARAMETER Invalid parameter.\r
1053 @retval EFI_NOT_FOUND No descriptor for the desired space exists.\r
162ed594 1054 @retval EFI_SUCCESS Space successfully allocated.\r
1055\r
1056**/\r
28a00297 1057EFI_STATUS\r
1058CoreAllocateSpace (\r
1059 IN UINTN Operation,\r
1060 IN EFI_GCD_ALLOCATE_TYPE GcdAllocateType,\r
1061 IN EFI_GCD_MEMORY_TYPE GcdMemoryType,\r
1062 IN EFI_GCD_IO_TYPE GcdIoType,\r
1063 IN UINTN Alignment,\r
1064 IN UINT64 Length,\r
1065 IN OUT EFI_PHYSICAL_ADDRESS *BaseAddress,\r
1066 IN EFI_HANDLE ImageHandle,\r
1067 IN EFI_HANDLE DeviceHandle OPTIONAL\r
1068 )\r
28a00297 1069{\r
1070 EFI_STATUS Status;\r
1071 EFI_PHYSICAL_ADDRESS AlignmentMask;\r
1072 EFI_PHYSICAL_ADDRESS MaxAddress;\r
1073 LIST_ENTRY *Map;\r
1074 LIST_ENTRY *Link;\r
1075 LIST_ENTRY *SubLink;\r
1076 EFI_GCD_MAP_ENTRY *Entry;\r
1077 EFI_GCD_MAP_ENTRY *TopEntry;\r
1078 EFI_GCD_MAP_ENTRY *BottomEntry;\r
1079 LIST_ENTRY *StartLink;\r
1080 LIST_ENTRY *EndLink;\r
1081 BOOLEAN Found;\r
1082\r
1083 //\r
1084 // Make sure parameters are valid\r
1085 //\r
3d78c020 1086 if ((UINT32)GcdAllocateType >= EfiGcdMaxAllocateType) {\r
aa927cae 1087 DEBUG ((DEBUG_GCD, " Status = %r\n", EFI_INVALID_PARAMETER));\r
28a00297 1088 return EFI_INVALID_PARAMETER;\r
1089 }\r
3d78c020 1090 if ((UINT32)GcdMemoryType >= EfiGcdMemoryTypeMaximum) {\r
aa927cae 1091 DEBUG ((DEBUG_GCD, " Status = %r\n", EFI_INVALID_PARAMETER));\r
28a00297 1092 return EFI_INVALID_PARAMETER;\r
1093 }\r
3d78c020 1094 if ((UINT32)GcdIoType >= EfiGcdIoTypeMaximum) {\r
aa927cae 1095 DEBUG ((DEBUG_GCD, " Status = %r\n", EFI_INVALID_PARAMETER));\r
28a00297 1096 return EFI_INVALID_PARAMETER;\r
1097 }\r
1098 if (BaseAddress == NULL) {\r
aa927cae 1099 DEBUG ((DEBUG_GCD, " Status = %r\n", EFI_INVALID_PARAMETER));\r
28a00297 1100 return EFI_INVALID_PARAMETER;\r
1101 }\r
1102 if (ImageHandle == NULL) {\r
aa927cae 1103 DEBUG ((DEBUG_GCD, " Status = %r\n", EFI_INVALID_PARAMETER));\r
28a00297 1104 return EFI_INVALID_PARAMETER;\r
1105 }\r
1106 if (Alignment >= 64) {\r
aa927cae 1107 DEBUG ((DEBUG_GCD, " Status = %r\n", EFI_NOT_FOUND));\r
28a00297 1108 return EFI_NOT_FOUND;\r
1109 }\r
1110 if (Length == 0) {\r
aa927cae 1111 DEBUG ((DEBUG_GCD, " Status = %r\n", EFI_INVALID_PARAMETER));\r
28a00297 1112 return EFI_INVALID_PARAMETER;\r
1113 }\r
1114\r
1115 Map = NULL;\r
71f68914 1116 if ((Operation & GCD_MEMORY_SPACE_OPERATION) != 0) {\r
28a00297 1117 CoreAcquireGcdMemoryLock ();\r
1118 Map = &mGcdMemorySpaceMap;\r
fbbb4211 1119 } else if ((Operation & GCD_IO_SPACE_OPERATION) != 0) {\r
28a00297 1120 CoreAcquireGcdIoLock ();\r
1121 Map = &mGcdIoSpaceMap;\r
fbbb4211 1122 } else {\r
1123 ASSERT (FALSE);\r
28a00297 1124 }\r
1125\r
1126 Found = FALSE;\r
1127 StartLink = NULL;\r
1128 EndLink = NULL;\r
1129 //\r
1130 // Compute alignment bit mask\r
1131 //\r
1132 AlignmentMask = LShiftU64 (1, Alignment) - 1;\r
1133\r
1134 if (GcdAllocateType == EfiGcdAllocateAddress) {\r
1135 //\r
1136 // Verify that the BaseAddress passed in is aligned correctly\r
1137 //\r
1138 if ((*BaseAddress & AlignmentMask) != 0) {\r
1139 Status = EFI_NOT_FOUND;\r
1140 goto Done;\r
1141 }\r
1142\r
1143 //\r
1144 // Search for the list of descriptors that cover the range BaseAddress to BaseAddress+Length\r
1145 //\r
1146 Status = CoreSearchGcdMapEntry (*BaseAddress, Length, &StartLink, &EndLink, Map);\r
1147 if (EFI_ERROR (Status)) {\r
1148 Status = EFI_NOT_FOUND;\r
1149 goto Done;\r
1150 }\r
d2fbaaab 1151 ASSERT (StartLink != NULL && EndLink != NULL);\r
28a00297 1152\r
1153 //\r
1154 // Verify that the list of descriptors are unallocated memory matching GcdMemoryType.\r
1155 //\r
1156 Link = StartLink;\r
1157 while (Link != EndLink->ForwardLink) {\r
1158 Entry = CR (Link, EFI_GCD_MAP_ENTRY, Link, EFI_GCD_MAP_SIGNATURE);\r
1159 Link = Link->ForwardLink;\r
1160 Status = CoreAllocateSpaceCheckEntry (Operation, Entry, GcdMemoryType, GcdIoType);\r
1161 if (EFI_ERROR (Status)) {\r
1162 goto Done;\r
1163 }\r
1164 }\r
1165 Found = TRUE;\r
1166 } else {\r
1167\r
1168 Entry = CR (Map->BackLink, EFI_GCD_MAP_ENTRY, Link, EFI_GCD_MAP_SIGNATURE);\r
1169\r
1170 //\r
1171 // Compute the maximum address to use in the search algorithm\r
1172 //\r
1173 if (GcdAllocateType == EfiGcdAllocateMaxAddressSearchBottomUp ||\r
1174 GcdAllocateType == EfiGcdAllocateMaxAddressSearchTopDown ) {\r
1175 MaxAddress = *BaseAddress;\r
1176 } else {\r
1177 MaxAddress = Entry->EndAddress;\r
1178 }\r
1179\r
1180 //\r
1181 // Verify that the list of descriptors are unallocated memory matching GcdMemoryType.\r
1182 //\r
1183 if (GcdAllocateType == EfiGcdAllocateMaxAddressSearchTopDown ||\r
1184 GcdAllocateType == EfiGcdAllocateAnySearchTopDown ) {\r
1185 Link = Map->BackLink;\r
1186 } else {\r
1187 Link = Map->ForwardLink;\r
1188 }\r
1189 while (Link != Map) {\r
1190 Entry = CR (Link, EFI_GCD_MAP_ENTRY, Link, EFI_GCD_MAP_SIGNATURE);\r
1191\r
1192 if (GcdAllocateType == EfiGcdAllocateMaxAddressSearchTopDown ||\r
1193 GcdAllocateType == EfiGcdAllocateAnySearchTopDown ) {\r
1194 Link = Link->BackLink;\r
1195 } else {\r
1196 Link = Link->ForwardLink;\r
1197 }\r
1198\r
1199 Status = CoreAllocateSpaceCheckEntry (Operation, Entry, GcdMemoryType, GcdIoType);\r
1200 if (EFI_ERROR (Status)) {\r
1201 continue;\r
1202 }\r
1203\r
1204 if (GcdAllocateType == EfiGcdAllocateMaxAddressSearchTopDown ||\r
e94a9ff7 1205 GcdAllocateType == EfiGcdAllocateAnySearchTopDown) {\r
28a00297 1206 if ((Entry->BaseAddress + Length) > MaxAddress) {\r
1207 continue;\r
1208 }\r
1209 if (Length > (Entry->EndAddress + 1)) {\r
1210 Status = EFI_NOT_FOUND;\r
1211 goto Done;\r
1212 }\r
1213 if (Entry->EndAddress > MaxAddress) {\r
1214 *BaseAddress = MaxAddress;\r
1215 } else {\r
1216 *BaseAddress = Entry->EndAddress;\r
1217 }\r
1218 *BaseAddress = (*BaseAddress + 1 - Length) & (~AlignmentMask);\r
1219 } else {\r
1220 *BaseAddress = (Entry->BaseAddress + AlignmentMask) & (~AlignmentMask);\r
1221 if ((*BaseAddress + Length - 1) > MaxAddress) {\r
1222 Status = EFI_NOT_FOUND;\r
1223 goto Done;\r
1224 }\r
1225 }\r
1226\r
1227 //\r
1228 // Search for the list of descriptors that cover the range BaseAddress to BaseAddress+Length\r
1229 //\r
1230 Status = CoreSearchGcdMapEntry (*BaseAddress, Length, &StartLink, &EndLink, Map);\r
1231 if (EFI_ERROR (Status)) {\r
1232 Status = EFI_NOT_FOUND;\r
1233 goto Done;\r
1234 }\r
d2fbaaab 1235 ASSERT (StartLink != NULL && EndLink != NULL);\r
28a00297 1236\r
1237 Link = StartLink;\r
1238 //\r
1239 // Verify that the list of descriptors are unallocated memory matching GcdMemoryType.\r
1240 //\r
1241 Found = TRUE;\r
1242 SubLink = StartLink;\r
1243 while (SubLink != EndLink->ForwardLink) {\r
1244 Entry = CR (SubLink, EFI_GCD_MAP_ENTRY, Link, EFI_GCD_MAP_SIGNATURE);\r
1245 Status = CoreAllocateSpaceCheckEntry (Operation, Entry, GcdMemoryType, GcdIoType);\r
1246 if (EFI_ERROR (Status)) {\r
1247 Link = SubLink;\r
1248 Found = FALSE;\r
1249 break;\r
1250 }\r
1251 SubLink = SubLink->ForwardLink;\r
1252 }\r
1253 if (Found) {\r
1254 break;\r
1255 }\r
1256 }\r
1257 }\r
1258 if (!Found) {\r
1259 Status = EFI_NOT_FOUND;\r
1260 goto Done;\r
1261 }\r
1262\r
1263 //\r
1264 // Allocate work space to perform this operation\r
1265 //\r
1266 Status = CoreAllocateGcdMapEntry (&TopEntry, &BottomEntry);\r
1267 if (EFI_ERROR (Status)) {\r
1268 Status = EFI_OUT_OF_RESOURCES;\r
1269 goto Done;\r
1270 }\r
d2fbaaab 1271 ASSERT (TopEntry != NULL && BottomEntry != NULL);\r
28a00297 1272\r
1273 //\r
1274 // Convert/Insert the list of descriptors from StartLink to EndLink\r
1275 //\r
1276 Link = StartLink;\r
1277 while (Link != EndLink->ForwardLink) {\r
1278 Entry = CR (Link, EFI_GCD_MAP_ENTRY, Link, EFI_GCD_MAP_SIGNATURE);\r
1279 CoreInsertGcdMapEntry (Link, Entry, *BaseAddress, Length, TopEntry, BottomEntry);\r
1280 Entry->ImageHandle = ImageHandle;\r
1281 Entry->DeviceHandle = DeviceHandle;\r
1282 Link = Link->ForwardLink;\r
1283 }\r
1284\r
1285 //\r
1286 // Cleanup\r
1287 //\r
1288 Status = CoreCleanupGcdMapEntry (TopEntry, BottomEntry, StartLink, EndLink, Map);\r
1289\r
1290Done:\r
aa927cae 1291 DEBUG ((DEBUG_GCD, " Status = %r", Status));\r
1292 if (!EFI_ERROR (Status)) {\r
1293 DEBUG ((DEBUG_GCD, " (BaseAddress = %016lx)", *BaseAddress));\r
1294 }\r
1295 DEBUG ((DEBUG_GCD, "\n"));\r
d1102dba 1296\r
71f68914 1297 if ((Operation & GCD_MEMORY_SPACE_OPERATION) != 0) {\r
28a00297 1298 CoreReleaseGcdMemoryLock ();\r
aa927cae 1299 CoreDumpGcdMemorySpaceMap (FALSE);\r
28a00297 1300 }\r
71f68914 1301 if ((Operation & GCD_IO_SPACE_OPERATION) !=0) {\r
28a00297 1302 CoreReleaseGcdIoLock ();\r
aa927cae 1303 CoreDumpGcdIoSpaceMap (FALSE);\r
28a00297 1304 }\r
aa927cae 1305\r
28a00297 1306 return Status;\r
1307}\r
1308\r
28a00297 1309\r
162ed594 1310/**\r
28a00297 1311 Add a segment of memory to GCD map.\r
1312\r
022c6d45 1313 @param GcdMemoryType Memory type of the segment.\r
1314 @param BaseAddress Base address of the segment.\r
1315 @param Length Length of the segment.\r
1316 @param Capabilities alterable attributes of the segment.\r
28a00297 1317\r
022c6d45 1318 @retval EFI_INVALID_PARAMETER Invalid parameters.\r
162ed594 1319 @retval EFI_SUCCESS Successfully add a segment of memory space.\r
28a00297 1320\r
162ed594 1321**/\r
162ed594 1322EFI_STATUS\r
1323CoreInternalAddMemorySpace (\r
1324 IN EFI_GCD_MEMORY_TYPE GcdMemoryType,\r
1325 IN EFI_PHYSICAL_ADDRESS BaseAddress,\r
1326 IN UINT64 Length,\r
1327 IN UINT64 Capabilities\r
1328 )\r
28a00297 1329{\r
f9d1f97c 1330 DEBUG ((DEBUG_GCD, "GCD:AddMemorySpace(Base=%016lx,Length=%016lx)\n", BaseAddress, Length));\r
1331 DEBUG ((DEBUG_GCD, " GcdMemoryType = %a\n", mGcdMemoryTypeNames[MIN (GcdMemoryType, EfiGcdMemoryTypeMaximum)]));\r
1332 DEBUG ((DEBUG_GCD, " Capabilities = %016lx\n", Capabilities));\r
1333\r
28a00297 1334 //\r
1335 // Make sure parameters are valid\r
1336 //\r
1337 if (GcdMemoryType <= EfiGcdMemoryTypeNonExistent || GcdMemoryType >= EfiGcdMemoryTypeMaximum) {\r
1338 return EFI_INVALID_PARAMETER;\r
1339 }\r
1340\r
1341 return CoreConvertSpace (GCD_ADD_MEMORY_OPERATION, GcdMemoryType, (EFI_GCD_IO_TYPE) 0, BaseAddress, Length, Capabilities, 0);\r
1342}\r
1343\r
1344//\r
1345// GCD Core Services\r
1346//\r
162ed594 1347\r
1348/**\r
1349 Allocates nonexistent memory, reserved memory, system memory, or memorymapped\r
1350 I/O resources from the global coherency domain of the processor.\r
1351\r
022c6d45 1352 @param GcdAllocateType The type of allocate operation\r
1353 @param GcdMemoryType The desired memory type\r
1354 @param Alignment Align with 2^Alignment\r
1355 @param Length Length to allocate\r
1356 @param BaseAddress Base address to allocate\r
1357 @param ImageHandle The image handle consume the allocated space.\r
1358 @param DeviceHandle The device handle consume the allocated space.\r
162ed594 1359\r
022c6d45 1360 @retval EFI_INVALID_PARAMETER Invalid parameter.\r
1361 @retval EFI_NOT_FOUND No descriptor contains the desired space.\r
162ed594 1362 @retval EFI_SUCCESS Memory space successfully allocated.\r
1363\r
1364**/\r
28a00297 1365EFI_STATUS\r
3b6ffb6a 1366EFIAPI\r
28a00297 1367CoreAllocateMemorySpace (\r
1368 IN EFI_GCD_ALLOCATE_TYPE GcdAllocateType,\r
1369 IN EFI_GCD_MEMORY_TYPE GcdMemoryType,\r
1370 IN UINTN Alignment,\r
1371 IN UINT64 Length,\r
1372 IN OUT EFI_PHYSICAL_ADDRESS *BaseAddress,\r
1373 IN EFI_HANDLE ImageHandle,\r
1374 IN EFI_HANDLE DeviceHandle OPTIONAL\r
1375 )\r
28a00297 1376{\r
7328295c
MK
1377 if (BaseAddress != NULL) {\r
1378 DEBUG ((DEBUG_GCD, "GCD:AllocateMemorySpace(Base=%016lx,Length=%016lx)\n", *BaseAddress, Length));\r
1379 } else {\r
1380 DEBUG ((DEBUG_GCD, "GCD:AllocateMemorySpace(Base=<NULL>,Length=%016lx)\n", Length));\r
1381 }\r
f9d1f97c 1382 DEBUG ((DEBUG_GCD, " GcdAllocateType = %a\n", mGcdAllocationTypeNames[MIN (GcdAllocateType, EfiGcdMaxAllocateType)]));\r
1383 DEBUG ((DEBUG_GCD, " GcdMemoryType = %a\n", mGcdMemoryTypeNames[MIN (GcdMemoryType, EfiGcdMemoryTypeMaximum)]));\r
1384 DEBUG ((DEBUG_GCD, " Alignment = %016lx\n", LShiftU64 (1, Alignment)));\r
1385 DEBUG ((DEBUG_GCD, " ImageHandle = %p\n", ImageHandle));\r
1386 DEBUG ((DEBUG_GCD, " DeviceHandle = %p\n", DeviceHandle));\r
d1102dba 1387\r
28a00297 1388 return CoreAllocateSpace (\r
022c6d45 1389 GCD_ALLOCATE_MEMORY_OPERATION,\r
1390 GcdAllocateType,\r
1391 GcdMemoryType,\r
1392 (EFI_GCD_IO_TYPE) 0,\r
1393 Alignment,\r
1394 Length,\r
1395 BaseAddress,\r
1396 ImageHandle,\r
28a00297 1397 DeviceHandle\r
1398 );\r
1399}\r
1400\r
162ed594 1401\r
1402/**\r
1403 Adds reserved memory, system memory, or memory-mapped I/O resources to the\r
1404 global coherency domain of the processor.\r
1405\r
022c6d45 1406 @param GcdMemoryType Memory type of the memory space.\r
1407 @param BaseAddress Base address of the memory space.\r
1408 @param Length Length of the memory space.\r
1409 @param Capabilities alterable attributes of the memory space.\r
162ed594 1410\r
1411 @retval EFI_SUCCESS Merged this memory space into GCD map.\r
1412\r
1413**/\r
28a00297 1414EFI_STATUS\r
3b6ffb6a 1415EFIAPI\r
28a00297 1416CoreAddMemorySpace (\r
1417 IN EFI_GCD_MEMORY_TYPE GcdMemoryType,\r
1418 IN EFI_PHYSICAL_ADDRESS BaseAddress,\r
1419 IN UINT64 Length,\r
1420 IN UINT64 Capabilities\r
1421 )\r
28a00297 1422{\r
1423 EFI_STATUS Status;\r
1424 EFI_PHYSICAL_ADDRESS PageBaseAddress;\r
1425 UINT64 PageLength;\r
1426\r
1427 Status = CoreInternalAddMemorySpace (GcdMemoryType, BaseAddress, Length, Capabilities);\r
1428\r
74705ca5 1429 if (!EFI_ERROR (Status) && ((GcdMemoryType == EfiGcdMemoryTypeSystemMemory) || (GcdMemoryType == EfiGcdMemoryTypeMoreReliable))) {\r
28a00297 1430\r
74705ca5 1431 PageBaseAddress = PageAlignAddress (BaseAddress);\r
28a00297 1432 PageLength = PageAlignLength (BaseAddress + Length - PageBaseAddress);\r
1433\r
1434 Status = CoreAllocateMemorySpace (\r
1435 EfiGcdAllocateAddress,\r
1436 GcdMemoryType,\r
022c6d45 1437 EFI_PAGE_SHIFT,\r
28a00297 1438 PageLength,\r
1439 &PageBaseAddress,\r
1440 gDxeCoreImageHandle,\r
1441 NULL\r
1442 );\r
1443\r
1444 if (!EFI_ERROR (Status)) {\r
1445 CoreAddMemoryDescriptor (\r
1446 EfiConventionalMemory,\r
1447 PageBaseAddress,\r
1448 RShiftU64 (PageLength, EFI_PAGE_SHIFT),\r
1449 Capabilities\r
1450 );\r
1451 } else {\r
1452 for (; PageLength != 0; PageLength -= EFI_PAGE_SIZE, PageBaseAddress += EFI_PAGE_SIZE) {\r
1453 Status = CoreAllocateMemorySpace (\r
1454 EfiGcdAllocateAddress,\r
1455 GcdMemoryType,\r
022c6d45 1456 EFI_PAGE_SHIFT,\r
28a00297 1457 EFI_PAGE_SIZE,\r
1458 &PageBaseAddress,\r
1459 gDxeCoreImageHandle,\r
1460 NULL\r
1461 );\r
1462\r
1463 if (!EFI_ERROR (Status)) {\r
1464 CoreAddMemoryDescriptor (\r
1465 EfiConventionalMemory,\r
1466 PageBaseAddress,\r
1467 1,\r
1468 Capabilities\r
1469 );\r
1470 }\r
1471 }\r
1472 }\r
1473 }\r
1474 return Status;\r
1475}\r
1476\r
28a00297 1477\r
162ed594 1478/**\r
28a00297 1479 Frees nonexistent memory, reserved memory, system memory, or memory-mapped\r
162ed594 1480 I/O resources from the global coherency domain of the processor.\r
28a00297 1481\r
022c6d45 1482 @param BaseAddress Base address of the memory space.\r
1483 @param Length Length of the memory space.\r
28a00297 1484\r
162ed594 1485 @retval EFI_SUCCESS Space successfully freed.\r
28a00297 1486\r
162ed594 1487**/\r
28a00297 1488EFI_STATUS\r
3b6ffb6a 1489EFIAPI\r
162ed594 1490CoreFreeMemorySpace (\r
28a00297 1491 IN EFI_PHYSICAL_ADDRESS BaseAddress,\r
1492 IN UINT64 Length\r
1493 )\r
162ed594 1494{\r
f9d1f97c 1495 DEBUG ((DEBUG_GCD, "GCD:FreeMemorySpace(Base=%016lx,Length=%016lx)\n", BaseAddress, Length));\r
1496\r
162ed594 1497 return CoreConvertSpace (GCD_FREE_MEMORY_OPERATION, (EFI_GCD_MEMORY_TYPE) 0, (EFI_GCD_IO_TYPE) 0, BaseAddress, Length, 0, 0);\r
1498}\r
28a00297 1499\r
28a00297 1500\r
162ed594 1501/**\r
28a00297 1502 Removes reserved memory, system memory, or memory-mapped I/O resources from\r
162ed594 1503 the global coherency domain of the processor.\r
28a00297 1504\r
022c6d45 1505 @param BaseAddress Base address of the memory space.\r
1506 @param Length Length of the memory space.\r
28a00297 1507\r
162ed594 1508 @retval EFI_SUCCESS Successfully remove a segment of memory space.\r
28a00297 1509\r
162ed594 1510**/\r
1511EFI_STATUS\r
3b6ffb6a 1512EFIAPI\r
162ed594 1513CoreRemoveMemorySpace (\r
1514 IN EFI_PHYSICAL_ADDRESS BaseAddress,\r
1515 IN UINT64 Length\r
1516 )\r
28a00297 1517{\r
f9d1f97c 1518 DEBUG ((DEBUG_GCD, "GCD:RemoveMemorySpace(Base=%016lx,Length=%016lx)\n", BaseAddress, Length));\r
d1102dba 1519\r
28a00297 1520 return CoreConvertSpace (GCD_REMOVE_MEMORY_OPERATION, (EFI_GCD_MEMORY_TYPE) 0, (EFI_GCD_IO_TYPE) 0, BaseAddress, Length, 0, 0);\r
1521}\r
1522\r
162ed594 1523\r
1524/**\r
1525 Build a memory descriptor according to an entry.\r
1526\r
022c6d45 1527 @param Descriptor The descriptor to be built\r
162ed594 1528 @param Entry According to this entry\r
1529\r
1530**/\r
28a00297 1531VOID\r
1532BuildMemoryDescriptor (\r
1533 IN OUT EFI_GCD_MEMORY_SPACE_DESCRIPTOR *Descriptor,\r
1534 IN EFI_GCD_MAP_ENTRY *Entry\r
1535 )\r
28a00297 1536{\r
1537 Descriptor->BaseAddress = Entry->BaseAddress;\r
1538 Descriptor->Length = Entry->EndAddress - Entry->BaseAddress + 1;\r
1539 Descriptor->Capabilities = Entry->Capabilities;\r
1540 Descriptor->Attributes = Entry->Attributes;\r
1541 Descriptor->GcdMemoryType = Entry->GcdMemoryType;\r
1542 Descriptor->ImageHandle = Entry->ImageHandle;\r
1543 Descriptor->DeviceHandle = Entry->DeviceHandle;\r
1544}\r
1545\r
28a00297 1546\r
162ed594 1547/**\r
28a00297 1548 Retrieves the descriptor for a memory region containing a specified address.\r
1549\r
022c6d45 1550 @param BaseAddress Specified start address\r
1551 @param Descriptor Specified length\r
28a00297 1552\r
022c6d45 1553 @retval EFI_INVALID_PARAMETER Invalid parameter\r
162ed594 1554 @retval EFI_SUCCESS Successfully get memory space descriptor.\r
28a00297 1555\r
162ed594 1556**/\r
1557EFI_STATUS\r
3b6ffb6a 1558EFIAPI\r
162ed594 1559CoreGetMemorySpaceDescriptor (\r
1560 IN EFI_PHYSICAL_ADDRESS BaseAddress,\r
1561 OUT EFI_GCD_MEMORY_SPACE_DESCRIPTOR *Descriptor\r
1562 )\r
28a00297 1563{\r
1564 EFI_STATUS Status;\r
1565 LIST_ENTRY *StartLink;\r
1566 LIST_ENTRY *EndLink;\r
1567 EFI_GCD_MAP_ENTRY *Entry;\r
1568\r
1569 //\r
1570 // Make sure parameters are valid\r
1571 //\r
1572 if (Descriptor == NULL) {\r
1573 return EFI_INVALID_PARAMETER;\r
1574 }\r
1575\r
1576 CoreAcquireGcdMemoryLock ();\r
1577\r
1578 //\r
022c6d45 1579 // Search for the list of descriptors that contain BaseAddress\r
28a00297 1580 //\r
1581 Status = CoreSearchGcdMapEntry (BaseAddress, 1, &StartLink, &EndLink, &mGcdMemorySpaceMap);\r
1582 if (EFI_ERROR (Status)) {\r
1583 Status = EFI_NOT_FOUND;\r
1584 } else {\r
d2fbaaab 1585 ASSERT (StartLink != NULL && EndLink != NULL);\r
28a00297 1586 //\r
1587 // Copy the contents of the found descriptor into Descriptor\r
1588 //\r
1589 Entry = CR (StartLink, EFI_GCD_MAP_ENTRY, Link, EFI_GCD_MAP_SIGNATURE);\r
1590 BuildMemoryDescriptor (Descriptor, Entry);\r
1591 }\r
1592\r
1593 CoreReleaseGcdMemoryLock ();\r
1594\r
1595 return Status;\r
1596}\r
1597\r
162ed594 1598\r
1599/**\r
1600 Modifies the attributes for a memory region in the global coherency domain of the\r
1601 processor.\r
1602\r
022c6d45 1603 @param BaseAddress Specified start address\r
1604 @param Length Specified length\r
1605 @param Attributes Specified attributes\r
162ed594 1606\r
fc8ff20f 1607 @retval EFI_SUCCESS The attributes were set for the memory region.\r
d1102dba 1608 @retval EFI_INVALID_PARAMETER Length is zero.\r
fc8ff20f 1609 @retval EFI_UNSUPPORTED The processor does not support one or more bytes of the memory\r
1610 resource range specified by BaseAddress and Length.\r
1611 @retval EFI_UNSUPPORTED The bit mask of attributes is not support for the memory resource\r
1612 range specified by BaseAddress and Length.\r
1613 @retval EFI_ACCESS_DEFINED The attributes for the memory resource range specified by\r
1614 BaseAddress and Length cannot be modified.\r
1615 @retval EFI_OUT_OF_RESOURCES There are not enough system resources to modify the attributes of\r
1616 the memory resource range.\r
1617 @retval EFI_NOT_AVAILABLE_YET The attributes cannot be set because CPU architectural protocol is\r
1618 not available yet.\r
162ed594 1619\r
1620**/\r
28a00297 1621EFI_STATUS\r
3b6ffb6a 1622EFIAPI\r
28a00297 1623CoreSetMemorySpaceAttributes (\r
1624 IN EFI_PHYSICAL_ADDRESS BaseAddress,\r
1625 IN UINT64 Length,\r
1626 IN UINT64 Attributes\r
1627 )\r
162ed594 1628{\r
f9d1f97c 1629 DEBUG ((DEBUG_GCD, "GCD:SetMemorySpaceAttributes(Base=%016lx,Length=%016lx)\n", BaseAddress, Length));\r
1630 DEBUG ((DEBUG_GCD, " Attributes = %016lx\n", Attributes));\r
1631\r
162ed594 1632 return CoreConvertSpace (GCD_SET_ATTRIBUTES_MEMORY_OPERATION, (EFI_GCD_MEMORY_TYPE) 0, (EFI_GCD_IO_TYPE) 0, BaseAddress, Length, 0, Attributes);\r
1633}\r
28a00297 1634\r
28a00297 1635\r
771ee501
EC
1636/**\r
1637 Modifies the capabilities for a memory region in the global coherency domain of the\r
1638 processor.\r
1639\r
1640 @param BaseAddress The physical address that is the start address of a memory region.\r
1641 @param Length The size in bytes of the memory region.\r
1642 @param Capabilities The bit mask of capabilities that the memory region supports.\r
1643\r
1644 @retval EFI_SUCCESS The capabilities were set for the memory region.\r
1645 @retval EFI_INVALID_PARAMETER Length is zero.\r
1646 @retval EFI_UNSUPPORTED The capabilities specified by Capabilities do not include the\r
1647 memory region attributes currently in use.\r
1648 @retval EFI_ACCESS_DENIED The capabilities for the memory resource range specified by\r
1649 BaseAddress and Length cannot be modified.\r
1650 @retval EFI_OUT_OF_RESOURCES There are not enough system resources to modify the capabilities\r
1651 of the memory resource range.\r
1652**/\r
1653EFI_STATUS\r
1654EFIAPI\r
1655CoreSetMemorySpaceCapabilities (\r
1656 IN EFI_PHYSICAL_ADDRESS BaseAddress,\r
1657 IN UINT64 Length,\r
1658 IN UINT64 Capabilities\r
1659 )\r
1660{\r
736a692e
HT
1661 EFI_STATUS Status;\r
1662\r
771ee501 1663 DEBUG ((DEBUG_GCD, "GCD:CoreSetMemorySpaceCapabilities(Base=%016lx,Length=%016lx)\n", BaseAddress, Length));\r
736a692e
HT
1664 DEBUG ((DEBUG_GCD, " Capabilities = %016lx\n", Capabilities));\r
1665\r
1666 Status = CoreConvertSpace (GCD_SET_CAPABILITIES_MEMORY_OPERATION, (EFI_GCD_MEMORY_TYPE) 0, (EFI_GCD_IO_TYPE) 0, BaseAddress, Length, Capabilities, 0);\r
771ee501 1667 if (!EFI_ERROR(Status)) {\r
32fd9c41 1668 CoreUpdateMemoryAttributes(BaseAddress, RShiftU64(Length, EFI_PAGE_SHIFT), Capabilities & (~EFI_MEMORY_RUNTIME));\r
736a692e
HT
1669 }\r
1670\r
771ee501
EC
1671 return Status;\r
1672}\r
1673\r
1674\r
162ed594 1675/**\r
1676 Returns a map of the memory resources in the global coherency domain of the\r
1677 processor.\r
28a00297 1678\r
022c6d45 1679 @param NumberOfDescriptors Number of descriptors.\r
1680 @param MemorySpaceMap Descriptor array\r
28a00297 1681\r
022c6d45 1682 @retval EFI_INVALID_PARAMETER Invalid parameter\r
1683 @retval EFI_OUT_OF_RESOURCES No enough buffer to allocate\r
162ed594 1684 @retval EFI_SUCCESS Successfully get memory space map.\r
28a00297 1685\r
162ed594 1686**/\r
28a00297 1687EFI_STATUS\r
3b6ffb6a 1688EFIAPI\r
28a00297 1689CoreGetMemorySpaceMap (\r
1690 OUT UINTN *NumberOfDescriptors,\r
1691 OUT EFI_GCD_MEMORY_SPACE_DESCRIPTOR **MemorySpaceMap\r
1692 )\r
28a00297 1693{\r
28a00297 1694 LIST_ENTRY *Link;\r
1695 EFI_GCD_MAP_ENTRY *Entry;\r
1696 EFI_GCD_MEMORY_SPACE_DESCRIPTOR *Descriptor;\r
bb685071 1697 UINTN DescriptorCount;\r
28a00297 1698\r
1699 //\r
1700 // Make sure parameters are valid\r
1701 //\r
1702 if (NumberOfDescriptors == NULL) {\r
1703 return EFI_INVALID_PARAMETER;\r
1704 }\r
1705 if (MemorySpaceMap == NULL) {\r
1706 return EFI_INVALID_PARAMETER;\r
1707 }\r
1708\r
bb685071
JW
1709 *NumberOfDescriptors = 0;\r
1710 *MemorySpaceMap = NULL;\r
28a00297 1711\r
1712 //\r
bb685071 1713 // Take the lock, for entering the loop with the lock held.\r
28a00297 1714 //\r
bb685071
JW
1715 CoreAcquireGcdMemoryLock ();\r
1716 while (TRUE) {\r
1717 //\r
1718 // Count descriptors. It might be done more than once because the\r
1719 // AllocatePool() called below has to be running outside the GCD lock.\r
1720 //\r
1721 DescriptorCount = CoreCountGcdMapEntry (&mGcdMemorySpaceMap);\r
61a62fc2 1722 if (DescriptorCount == *NumberOfDescriptors && *MemorySpaceMap != NULL) {\r
bb685071
JW
1723 //\r
1724 // Fill in the MemorySpaceMap if no memory space map change.\r
1725 //\r
1726 Descriptor = *MemorySpaceMap;\r
1727 Link = mGcdMemorySpaceMap.ForwardLink;\r
1728 while (Link != &mGcdMemorySpaceMap) {\r
1729 Entry = CR (Link, EFI_GCD_MAP_ENTRY, Link, EFI_GCD_MAP_SIGNATURE);\r
1730 BuildMemoryDescriptor (Descriptor, Entry);\r
1731 Descriptor++;\r
1732 Link = Link->ForwardLink;\r
1733 }\r
1734 //\r
1735 // We're done; exit the loop with the lock held.\r
1736 //\r
1737 break;\r
1738 }\r
28a00297 1739\r
bb685071
JW
1740 //\r
1741 // Release the lock before memory allocation, because it might cause\r
1742 // GCD lock conflict in one of calling path in AllocatPool().\r
1743 //\r
1744 CoreReleaseGcdMemoryLock ();\r
28a00297 1745\r
bb685071
JW
1746 //\r
1747 // Allocate memory to store the MemorySpaceMap. Note it might be already\r
1748 // allocated if there's map descriptor change during memory allocation at\r
1749 // last time.\r
1750 //\r
1751 if (*MemorySpaceMap != NULL) {\r
1752 FreePool (*MemorySpaceMap);\r
1753 }\r
1754\r
1755 *MemorySpaceMap = AllocatePool (DescriptorCount *\r
1756 sizeof (EFI_GCD_MEMORY_SPACE_DESCRIPTOR));\r
1757 if (*MemorySpaceMap == NULL) {\r
1758 *NumberOfDescriptors = 0;\r
1759 return EFI_OUT_OF_RESOURCES;\r
1760 }\r
1761\r
1762 //\r
1763 // Save the descriptor count got before for another round of check to make\r
1764 // sure we won't miss any, since we have code running outside the GCD lock.\r
1765 //\r
1766 *NumberOfDescriptors = DescriptorCount;\r
1767 //\r
1768 // Re-acquire the lock, for the next iteration.\r
1769 //\r
1770 CoreAcquireGcdMemoryLock ();\r
1771 }\r
28a00297 1772 //\r
bb685071 1773 // We exited the loop with the lock held, release it.\r
28a00297 1774 //\r
28a00297 1775 CoreReleaseGcdMemoryLock ();\r
bb685071
JW
1776\r
1777 return EFI_SUCCESS;\r
28a00297 1778}\r
1779\r
162ed594 1780\r
1781/**\r
1782 Adds reserved I/O or I/O resources to the global coherency domain of the processor.\r
1783\r
022c6d45 1784 @param GcdIoType IO type of the segment.\r
1785 @param BaseAddress Base address of the segment.\r
1786 @param Length Length of the segment.\r
162ed594 1787\r
022c6d45 1788 @retval EFI_SUCCESS Merged this segment into GCD map.\r
162ed594 1789 @retval EFI_INVALID_PARAMETER Parameter not valid\r
1790\r
1791**/\r
28a00297 1792EFI_STATUS\r
3b6ffb6a 1793EFIAPI\r
28a00297 1794CoreAddIoSpace (\r
1795 IN EFI_GCD_IO_TYPE GcdIoType,\r
1796 IN EFI_PHYSICAL_ADDRESS BaseAddress,\r
1797 IN UINT64 Length\r
1798 )\r
28a00297 1799{\r
f9d1f97c 1800 DEBUG ((DEBUG_GCD, "GCD:AddIoSpace(Base=%016lx,Length=%016lx)\n", BaseAddress, Length));\r
1801 DEBUG ((DEBUG_GCD, " GcdIoType = %a\n", mGcdIoTypeNames[MIN (GcdIoType, EfiGcdIoTypeMaximum)]));\r
d1102dba 1802\r
28a00297 1803 //\r
1804 // Make sure parameters are valid\r
1805 //\r
1806 if (GcdIoType <= EfiGcdIoTypeNonExistent || GcdIoType >= EfiGcdIoTypeMaximum) {\r
1807 return EFI_INVALID_PARAMETER;\r
1808 }\r
1809 return CoreConvertSpace (GCD_ADD_IO_OPERATION, (EFI_GCD_MEMORY_TYPE) 0, GcdIoType, BaseAddress, Length, 0, 0);\r
1810}\r
1811\r
162ed594 1812\r
1813/**\r
1814 Allocates nonexistent I/O, reserved I/O, or I/O resources from the global coherency\r
1815 domain of the processor.\r
1816\r
022c6d45 1817 @param GcdAllocateType The type of allocate operation\r
1818 @param GcdIoType The desired IO type\r
1819 @param Alignment Align with 2^Alignment\r
1820 @param Length Length to allocate\r
1821 @param BaseAddress Base address to allocate\r
1822 @param ImageHandle The image handle consume the allocated space.\r
1823 @param DeviceHandle The device handle consume the allocated space.\r
162ed594 1824\r
022c6d45 1825 @retval EFI_INVALID_PARAMETER Invalid parameter.\r
1826 @retval EFI_NOT_FOUND No descriptor contains the desired space.\r
162ed594 1827 @retval EFI_SUCCESS IO space successfully allocated.\r
1828\r
1829**/\r
28a00297 1830EFI_STATUS\r
3b6ffb6a 1831EFIAPI\r
28a00297 1832CoreAllocateIoSpace (\r
1833 IN EFI_GCD_ALLOCATE_TYPE GcdAllocateType,\r
1834 IN EFI_GCD_IO_TYPE GcdIoType,\r
1835 IN UINTN Alignment,\r
1836 IN UINT64 Length,\r
1837 IN OUT EFI_PHYSICAL_ADDRESS *BaseAddress,\r
1838 IN EFI_HANDLE ImageHandle,\r
1839 IN EFI_HANDLE DeviceHandle OPTIONAL\r
1840 )\r
28a00297 1841{\r
7328295c
MK
1842 if (BaseAddress != NULL) {\r
1843 DEBUG ((DEBUG_GCD, "GCD:AllocateIoSpace(Base=%016lx,Length=%016lx)\n", *BaseAddress, Length));\r
1844 } else {\r
1845 DEBUG ((DEBUG_GCD, "GCD:AllocateIoSpace(Base=<NULL>,Length=%016lx)\n", Length));\r
1846 }\r
f9d1f97c 1847 DEBUG ((DEBUG_GCD, " GcdAllocateType = %a\n", mGcdAllocationTypeNames[MIN (GcdAllocateType, EfiGcdMaxAllocateType)]));\r
5d1cf216 1848 DEBUG ((DEBUG_GCD, " GcdIoType = %a\n", mGcdIoTypeNames[MIN (GcdIoType, EfiGcdIoTypeMaximum)]));\r
f9d1f97c 1849 DEBUG ((DEBUG_GCD, " Alignment = %016lx\n", LShiftU64 (1, Alignment)));\r
1850 DEBUG ((DEBUG_GCD, " ImageHandle = %p\n", ImageHandle));\r
1851 DEBUG ((DEBUG_GCD, " DeviceHandle = %p\n", DeviceHandle));\r
d1102dba 1852\r
28a00297 1853 return CoreAllocateSpace (\r
022c6d45 1854 GCD_ALLOCATE_IO_OPERATION,\r
1855 GcdAllocateType,\r
1856 (EFI_GCD_MEMORY_TYPE) 0,\r
1857 GcdIoType,\r
1858 Alignment,\r
1859 Length,\r
1860 BaseAddress,\r
1861 ImageHandle,\r
28a00297 1862 DeviceHandle\r
1863 );\r
1864}\r
1865\r
28a00297 1866\r
162ed594 1867/**\r
28a00297 1868 Frees nonexistent I/O, reserved I/O, or I/O resources from the global coherency\r
162ed594 1869 domain of the processor.\r
28a00297 1870\r
022c6d45 1871 @param BaseAddress Base address of the segment.\r
1872 @param Length Length of the segment.\r
28a00297 1873\r
162ed594 1874 @retval EFI_SUCCESS Space successfully freed.\r
28a00297 1875\r
162ed594 1876**/\r
28a00297 1877EFI_STATUS\r
3b6ffb6a 1878EFIAPI\r
162ed594 1879CoreFreeIoSpace (\r
28a00297 1880 IN EFI_PHYSICAL_ADDRESS BaseAddress,\r
1881 IN UINT64 Length\r
1882 )\r
162ed594 1883{\r
f9d1f97c 1884 DEBUG ((DEBUG_GCD, "GCD:FreeIoSpace(Base=%016lx,Length=%016lx)\n", BaseAddress, Length));\r
1885\r
162ed594 1886 return CoreConvertSpace (GCD_FREE_IO_OPERATION, (EFI_GCD_MEMORY_TYPE) 0, (EFI_GCD_IO_TYPE) 0, BaseAddress, Length, 0, 0);\r
1887}\r
28a00297 1888\r
28a00297 1889\r
162ed594 1890/**\r
28a00297 1891 Removes reserved I/O or I/O resources from the global coherency domain of the\r
162ed594 1892 processor.\r
28a00297 1893\r
022c6d45 1894 @param BaseAddress Base address of the segment.\r
1895 @param Length Length of the segment.\r
28a00297 1896\r
162ed594 1897 @retval EFI_SUCCESS Successfully removed a segment of IO space.\r
28a00297 1898\r
162ed594 1899**/\r
1900EFI_STATUS\r
3b6ffb6a 1901EFIAPI\r
162ed594 1902CoreRemoveIoSpace (\r
1903 IN EFI_PHYSICAL_ADDRESS BaseAddress,\r
1904 IN UINT64 Length\r
1905 )\r
28a00297 1906{\r
f9d1f97c 1907 DEBUG ((DEBUG_GCD, "GCD:RemoveIoSpace(Base=%016lx,Length=%016lx)\n", BaseAddress, Length));\r
d1102dba 1908\r
28a00297 1909 return CoreConvertSpace (GCD_REMOVE_IO_OPERATION, (EFI_GCD_MEMORY_TYPE) 0, (EFI_GCD_IO_TYPE) 0, BaseAddress, Length, 0, 0);\r
1910}\r
1911\r
162ed594 1912\r
1913/**\r
1914 Build a IO descriptor according to an entry.\r
1915\r
022c6d45 1916 @param Descriptor The descriptor to be built\r
162ed594 1917 @param Entry According to this entry\r
1918\r
1919**/\r
28a00297 1920VOID\r
1921BuildIoDescriptor (\r
1922 IN EFI_GCD_IO_SPACE_DESCRIPTOR *Descriptor,\r
1923 IN EFI_GCD_MAP_ENTRY *Entry\r
1924 )\r
28a00297 1925{\r
1926 Descriptor->BaseAddress = Entry->BaseAddress;\r
1927 Descriptor->Length = Entry->EndAddress - Entry->BaseAddress + 1;\r
1928 Descriptor->GcdIoType = Entry->GcdIoType;\r
1929 Descriptor->ImageHandle = Entry->ImageHandle;\r
1930 Descriptor->DeviceHandle = Entry->DeviceHandle;\r
1931}\r
1932\r
28a00297 1933\r
162ed594 1934/**\r
28a00297 1935 Retrieves the descriptor for an I/O region containing a specified address.\r
1936\r
022c6d45 1937 @param BaseAddress Specified start address\r
1938 @param Descriptor Specified length\r
28a00297 1939\r
022c6d45 1940 @retval EFI_INVALID_PARAMETER Descriptor is NULL.\r
162ed594 1941 @retval EFI_SUCCESS Successfully get the IO space descriptor.\r
28a00297 1942\r
162ed594 1943**/\r
1944EFI_STATUS\r
3b6ffb6a 1945EFIAPI\r
162ed594 1946CoreGetIoSpaceDescriptor (\r
1947 IN EFI_PHYSICAL_ADDRESS BaseAddress,\r
1948 OUT EFI_GCD_IO_SPACE_DESCRIPTOR *Descriptor\r
1949 )\r
28a00297 1950{\r
1951 EFI_STATUS Status;\r
1952 LIST_ENTRY *StartLink;\r
1953 LIST_ENTRY *EndLink;\r
1954 EFI_GCD_MAP_ENTRY *Entry;\r
1955\r
1956 //\r
1957 // Make sure parameters are valid\r
1958 //\r
1959 if (Descriptor == NULL) {\r
1960 return EFI_INVALID_PARAMETER;\r
1961 }\r
1962\r
1963 CoreAcquireGcdIoLock ();\r
1964\r
1965 //\r
022c6d45 1966 // Search for the list of descriptors that contain BaseAddress\r
28a00297 1967 //\r
1968 Status = CoreSearchGcdMapEntry (BaseAddress, 1, &StartLink, &EndLink, &mGcdIoSpaceMap);\r
1969 if (EFI_ERROR (Status)) {\r
1970 Status = EFI_NOT_FOUND;\r
1971 } else {\r
d2fbaaab 1972 ASSERT (StartLink != NULL && EndLink != NULL);\r
28a00297 1973 //\r
1974 // Copy the contents of the found descriptor into Descriptor\r
1975 //\r
1976 Entry = CR (StartLink, EFI_GCD_MAP_ENTRY, Link, EFI_GCD_MAP_SIGNATURE);\r
1977 BuildIoDescriptor (Descriptor, Entry);\r
1978 }\r
1979\r
1980 CoreReleaseGcdIoLock ();\r
1981\r
1982 return Status;\r
1983}\r
1984\r
28a00297 1985\r
162ed594 1986/**\r
28a00297 1987 Returns a map of the I/O resources in the global coherency domain of the processor.\r
1988\r
022c6d45 1989 @param NumberOfDescriptors Number of descriptors.\r
1990 @param IoSpaceMap Descriptor array\r
28a00297 1991\r
022c6d45 1992 @retval EFI_INVALID_PARAMETER Invalid parameter\r
1993 @retval EFI_OUT_OF_RESOURCES No enough buffer to allocate\r
162ed594 1994 @retval EFI_SUCCESS Successfully get IO space map.\r
28a00297 1995\r
162ed594 1996**/\r
1997EFI_STATUS\r
3b6ffb6a 1998EFIAPI\r
162ed594 1999CoreGetIoSpaceMap (\r
2000 OUT UINTN *NumberOfDescriptors,\r
2001 OUT EFI_GCD_IO_SPACE_DESCRIPTOR **IoSpaceMap\r
2002 )\r
28a00297 2003{\r
2004 EFI_STATUS Status;\r
2005 LIST_ENTRY *Link;\r
2006 EFI_GCD_MAP_ENTRY *Entry;\r
2007 EFI_GCD_IO_SPACE_DESCRIPTOR *Descriptor;\r
2008\r
2009 //\r
2010 // Make sure parameters are valid\r
2011 //\r
2012 if (NumberOfDescriptors == NULL) {\r
2013 return EFI_INVALID_PARAMETER;\r
2014 }\r
2015 if (IoSpaceMap == NULL) {\r
2016 return EFI_INVALID_PARAMETER;\r
2017 }\r
2018\r
2019 CoreAcquireGcdIoLock ();\r
2020\r
2021 //\r
2022 // Count the number of descriptors\r
2023 //\r
2024 *NumberOfDescriptors = CoreCountGcdMapEntry (&mGcdIoSpaceMap);\r
2025\r
2026 //\r
2027 // Allocate the IoSpaceMap\r
2028 //\r
9c4ac31c 2029 *IoSpaceMap = AllocatePool (*NumberOfDescriptors * sizeof (EFI_GCD_IO_SPACE_DESCRIPTOR));\r
28a00297 2030 if (*IoSpaceMap == NULL) {\r
2031 Status = EFI_OUT_OF_RESOURCES;\r
2032 goto Done;\r
2033 }\r
2034\r
2035 //\r
2036 // Fill in the IoSpaceMap\r
2037 //\r
2038 Descriptor = *IoSpaceMap;\r
2039 Link = mGcdIoSpaceMap.ForwardLink;\r
2040 while (Link != &mGcdIoSpaceMap) {\r
2041 Entry = CR (Link, EFI_GCD_MAP_ENTRY, Link, EFI_GCD_MAP_SIGNATURE);\r
2042 BuildIoDescriptor (Descriptor, Entry);\r
2043 Descriptor++;\r
2044 Link = Link->ForwardLink;\r
2045 }\r
2046 Status = EFI_SUCCESS;\r
2047\r
2048Done:\r
2049 CoreReleaseGcdIoLock ();\r
2050 return Status;\r
022c6d45 2051}\r
28a00297 2052\r
aa927cae 2053\r
162ed594 2054/**\r
2055 Converts a Resource Descriptor HOB attributes mask to an EFI Memory Descriptor\r
2056 capabilities mask\r
2057\r
022c6d45 2058 @param GcdMemoryType Type of resource in the GCD memory map.\r
2059 @param Attributes The attribute mask in the Resource Descriptor\r
2060 HOB.\r
162ed594 2061\r
2062 @return The capabilities mask for an EFI Memory Descriptor.\r
2063\r
2064**/\r
28a00297 2065UINT64\r
2066CoreConvertResourceDescriptorHobAttributesToCapabilities (\r
2067 EFI_GCD_MEMORY_TYPE GcdMemoryType,\r
2068 UINT64 Attributes\r
2069 )\r
28a00297 2070{\r
2071 UINT64 Capabilities;\r
2072 GCD_ATTRIBUTE_CONVERSION_ENTRY *Conversion;\r
022c6d45 2073\r
28a00297 2074 //\r
2075 // Convert the Resource HOB Attributes to an EFI Memory Capabilities mask\r
2076 //\r
2077 for (Capabilities = 0, Conversion = mAttributeConversionTable; Conversion->Attribute != 0; Conversion++) {\r
74705ca5 2078 if (Conversion->Memory || ((GcdMemoryType != EfiGcdMemoryTypeSystemMemory) && (GcdMemoryType != EfiGcdMemoryTypeMoreReliable))) {\r
28a00297 2079 if (Attributes & Conversion->Attribute) {\r
2080 Capabilities |= Conversion->Capability;\r
2081 }\r
2082 }\r
2083 }\r
022c6d45 2084\r
28a00297 2085 return Capabilities;\r
2086}\r
2087\r
3a05b131
SZ
2088/**\r
2089 Calculate total memory bin size neeeded.\r
2090\r
2091 @return The total memory bin size neeeded.\r
2092\r
2093**/\r
2094UINT64\r
2095CalculateTotalMemoryBinSizeNeeded (\r
2096 VOID\r
2097 )\r
2098{\r
2099 UINTN Index;\r
2100 UINT64 TotalSize;\r
2101\r
2102 //\r
2103 // Loop through each memory type in the order specified by the gMemoryTypeInformation[] array\r
2104 //\r
2105 TotalSize = 0;\r
2106 for (Index = 0; gMemoryTypeInformation[Index].Type != EfiMaxMemoryType; Index++) {\r
2107 TotalSize += LShiftU64 (gMemoryTypeInformation[Index].NumberOfPages, EFI_PAGE_SHIFT);\r
2108 }\r
2109\r
2110 return TotalSize;\r
2111}\r
28a00297 2112\r
162ed594 2113/**\r
c18f12d3 2114 External function. Initializes memory services based on the memory\r
2115 descriptor HOBs. This function is responsible for priming the memory\r
2116 map, so memory allocations and resource allocations can be made.\r
2117 The first part of this function can not depend on any memory services\r
2118 until at least one memory descriptor is provided to the memory services.\r
28a00297 2119\r
022c6d45 2120 @param HobStart The start address of the HOB.\r
2121 @param MemoryBaseAddress Start address of memory region found to init DXE\r
2122 core.\r
2123 @param MemoryLength Length of memory region found to init DXE core.\r
28a00297 2124\r
162ed594 2125 @retval EFI_SUCCESS Memory services successfully initialized.\r
28a00297 2126\r
162ed594 2127**/\r
2128EFI_STATUS\r
2129CoreInitializeMemoryServices (\r
2130 IN VOID **HobStart,\r
2131 OUT EFI_PHYSICAL_ADDRESS *MemoryBaseAddress,\r
2132 OUT UINT64 *MemoryLength\r
2133 )\r
28a00297 2134{\r
2135 EFI_PEI_HOB_POINTERS Hob;\r
2136 EFI_MEMORY_TYPE_INFORMATION *EfiMemoryTypeInformation;\r
2137 UINTN DataSize;\r
2138 BOOLEAN Found;\r
2139 EFI_HOB_HANDOFF_INFO_TABLE *PhitHob;\r
2140 EFI_HOB_RESOURCE_DESCRIPTOR *ResourceHob;\r
2141 EFI_HOB_RESOURCE_DESCRIPTOR *PhitResourceHob;\r
2142 EFI_PHYSICAL_ADDRESS BaseAddress;\r
2143 UINT64 Length;\r
2144 UINT64 Attributes;\r
2145 UINT64 Capabilities;\r
c4c085a2 2146 EFI_PHYSICAL_ADDRESS TestedMemoryBaseAddress;\r
2147 UINT64 TestedMemoryLength;\r
28a00297 2148 EFI_PHYSICAL_ADDRESS HighAddress;\r
28a00297 2149 EFI_HOB_GUID_TYPE *GuidHob;\r
3a05b131
SZ
2150 UINT32 ReservedCodePageNumber;\r
2151 UINT64 MinimalMemorySizeNeeded;\r
28a00297 2152\r
2153 //\r
2154 // Point at the first HOB. This must be the PHIT HOB.\r
2155 //\r
2156 Hob.Raw = *HobStart;\r
2157 ASSERT (GET_HOB_TYPE (Hob) == EFI_HOB_TYPE_HANDOFF);\r
2158\r
2159 //\r
2160 // Initialize the spin locks and maps in the memory services.\r
2161 // Also fill in the memory services into the EFI Boot Services Table\r
2162 //\r
2163 CoreInitializePool ();\r
2164\r
2165 //\r
2166 // Initialize Local Variables\r
2167 //\r
2168 PhitResourceHob = NULL;\r
28a00297 2169 ResourceHob = NULL;\r
2170 BaseAddress = 0;\r
2171 Length = 0;\r
2172 Attributes = 0;\r
28a00297 2173\r
2174 //\r
2175 // Cache the PHIT HOB for later use\r
2176 //\r
2177 PhitHob = Hob.HandoffInformationTable;\r
d1102dba 2178\r
852081fc 2179 if (PcdGet64(PcdLoadModuleAtFixAddressEnable) != 0) {\r
d1102dba
LG
2180 ReservedCodePageNumber = PcdGet32(PcdLoadFixAddressRuntimeCodePageNumber);\r
2181 ReservedCodePageNumber += PcdGet32(PcdLoadFixAddressBootTimeCodePageNumber);\r
2182\r
2183 //\r
2184 // cache the Top address for loading modules at Fixed Address\r
2185 //\r
2186 gLoadModuleAtFixAddressConfigurationTable.DxeCodeTopAddress = PhitHob->EfiMemoryTop\r
54ea99a7 2187 + EFI_PAGES_TO_SIZE(ReservedCodePageNumber);\r
2188 }\r
28a00297 2189 //\r
2190 // See if a Memory Type Information HOB is available\r
2191 //\r
2192 GuidHob = GetFirstGuidHob (&gEfiMemoryTypeInformationGuid);\r
2193 if (GuidHob != NULL) {\r
2194 EfiMemoryTypeInformation = GET_GUID_HOB_DATA (GuidHob);\r
2195 DataSize = GET_GUID_HOB_DATA_SIZE (GuidHob);\r
2196 if (EfiMemoryTypeInformation != NULL && DataSize > 0 && DataSize <= (EfiMaxMemoryType + 1) * sizeof (EFI_MEMORY_TYPE_INFORMATION)) {\r
2197 CopyMem (&gMemoryTypeInformation, EfiMemoryTypeInformation, DataSize);\r
2198 }\r
2199 }\r
2200\r
3a05b131
SZ
2201 //\r
2202 // Include the total memory bin size needed to make sure memory bin could be allocated successfully.\r
2203 //\r
2204 MinimalMemorySizeNeeded = MINIMUM_INITIAL_MEMORY_SIZE + CalculateTotalMemoryBinSizeNeeded ();\r
2205\r
28a00297 2206 //\r
c4c085a2 2207 // Find the Resource Descriptor HOB that contains PHIT range EfiFreeMemoryBottom..EfiFreeMemoryTop\r
28a00297 2208 //\r
28a00297 2209 Found = FALSE;\r
2210 for (Hob.Raw = *HobStart; !END_OF_HOB_LIST(Hob); Hob.Raw = GET_NEXT_HOB(Hob)) {\r
c4c085a2 2211 //\r
2212 // Skip all HOBs except Resource Descriptor HOBs\r
2213 //\r
2214 if (GET_HOB_TYPE (Hob) != EFI_HOB_TYPE_RESOURCE_DESCRIPTOR) {\r
2215 continue;\r
2216 }\r
28a00297 2217\r
c4c085a2 2218 //\r
2219 // Skip Resource Descriptor HOBs that do not describe tested system memory\r
2220 //\r
2221 ResourceHob = Hob.ResourceDescriptor;\r
2222 if (ResourceHob->ResourceType != EFI_RESOURCE_SYSTEM_MEMORY) {\r
2223 continue;\r
2224 }\r
2225 if ((ResourceHob->ResourceAttribute & MEMORY_ATTRIBUTE_MASK) != TESTED_MEMORY_ATTRIBUTES) {\r
2226 continue;\r
2227 }\r
2228\r
2229 //\r
2230 // Skip Resource Descriptor HOBs that do not contain the PHIT range EfiFreeMemoryBottom..EfiFreeMemoryTop\r
2231 //\r
2232 if (PhitHob->EfiFreeMemoryBottom < ResourceHob->PhysicalStart) {\r
2233 continue;\r
2234 }\r
2235 if (PhitHob->EfiFreeMemoryTop > (ResourceHob->PhysicalStart + ResourceHob->ResourceLength)) {\r
2236 continue;\r
2237 }\r
2238\r
2239 //\r
2240 // Cache the resource descriptor HOB for the memory region described by the PHIT HOB\r
2241 //\r
2242 PhitResourceHob = ResourceHob;\r
2243 Found = TRUE;\r
2244\r
2245 //\r
3a05b131 2246 // Compute range between PHIT EfiMemoryTop and the end of the Resource Descriptor HOB\r
c4c085a2 2247 //\r
2248 Attributes = PhitResourceHob->ResourceAttribute;\r
2249 BaseAddress = PageAlignAddress (PhitHob->EfiMemoryTop);\r
2250 Length = PageAlignLength (ResourceHob->PhysicalStart + ResourceHob->ResourceLength - BaseAddress);\r
3a05b131 2251 if (Length < MinimalMemorySizeNeeded) {\r
c4c085a2 2252 //\r
d1102dba 2253 // If that range is not large enough to intialize the DXE Core, then\r
c4c085a2 2254 // Compute range between PHIT EfiFreeMemoryBottom and PHIT EfiFreeMemoryTop\r
2255 //\r
2256 BaseAddress = PageAlignAddress (PhitHob->EfiFreeMemoryBottom);\r
2257 Length = PageAlignLength (PhitHob->EfiFreeMemoryTop - BaseAddress);\r
3a05b131 2258 if (Length < MinimalMemorySizeNeeded) {\r
c4c085a2 2259 //\r
d1102dba 2260 // If that range is not large enough to intialize the DXE Core, then\r
c4c085a2 2261 // Compute range between the start of the Resource Descriptor HOB and the start of the HOB List\r
2262 //\r
2263 BaseAddress = PageAlignAddress (ResourceHob->PhysicalStart);\r
2264 Length = PageAlignLength ((UINT64)((UINTN)*HobStart - BaseAddress));\r
28a00297 2265 }\r
2266 }\r
c4c085a2 2267 break;\r
28a00297 2268 }\r
2269\r
2270 //\r
2271 // Assert if a resource descriptor HOB for the memory region described by the PHIT was not found\r
2272 //\r
2273 ASSERT (Found);\r
2274\r
2275 //\r
3a05b131
SZ
2276 // Take the range in the resource descriptor HOB for the memory region described\r
2277 // by the PHIT as higher priority if it is big enough. It can make the memory bin\r
2278 // allocated to be at the same memory region with PHIT that has more better compatibility\r
2279 // to avoid memory fragmentation for some code practices assume and allocate <4G ACPI memory.\r
28a00297 2280 //\r
3a05b131 2281 if (Length < MinimalMemorySizeNeeded) {\r
c4c085a2 2282 //\r
3a05b131
SZ
2283 // Search all the resource descriptor HOBs from the highest possible addresses down for a memory\r
2284 // region that is big enough to initialize the DXE core. Always skip the PHIT Resource HOB.\r
2285 // The max address must be within the physically addressible range for the processor.\r
c4c085a2 2286 //\r
36b07547 2287 HighAddress = MAX_ALLOC_ADDRESS;\r
3a05b131
SZ
2288 for (Hob.Raw = *HobStart; !END_OF_HOB_LIST(Hob); Hob.Raw = GET_NEXT_HOB(Hob)) {\r
2289 //\r
2290 // Skip the Resource Descriptor HOB that contains the PHIT\r
2291 //\r
2292 if (Hob.ResourceDescriptor == PhitResourceHob) {\r
2293 continue;\r
2294 }\r
2295 //\r
2296 // Skip all HOBs except Resource Descriptor HOBs\r
2297 //\r
2298 if (GET_HOB_TYPE (Hob) != EFI_HOB_TYPE_RESOURCE_DESCRIPTOR) {\r
2299 continue;\r
2300 }\r
28a00297 2301\r
3a05b131 2302 //\r
36b07547 2303 // Skip Resource Descriptor HOBs that do not describe tested system memory below MAX_ALLOC_ADDRESS\r
3a05b131
SZ
2304 //\r
2305 ResourceHob = Hob.ResourceDescriptor;\r
2306 if (ResourceHob->ResourceType != EFI_RESOURCE_SYSTEM_MEMORY) {\r
2307 continue;\r
2308 }\r
2309 if ((ResourceHob->ResourceAttribute & MEMORY_ATTRIBUTE_MASK) != TESTED_MEMORY_ATTRIBUTES) {\r
2310 continue;\r
2311 }\r
36b07547 2312 if ((ResourceHob->PhysicalStart + ResourceHob->ResourceLength) > (EFI_PHYSICAL_ADDRESS)MAX_ALLOC_ADDRESS) {\r
3a05b131
SZ
2313 continue;\r
2314 }\r
c4c085a2 2315\r
3a05b131
SZ
2316 //\r
2317 // Skip Resource Descriptor HOBs that are below a previously found Resource Descriptor HOB\r
2318 //\r
36b07547 2319 if (HighAddress != (EFI_PHYSICAL_ADDRESS)MAX_ALLOC_ADDRESS && ResourceHob->PhysicalStart <= HighAddress) {\r
3a05b131
SZ
2320 continue;\r
2321 }\r
2322\r
2323 //\r
2324 // Skip Resource Descriptor HOBs that are not large enough to initilize the DXE Core\r
2325 //\r
2326 TestedMemoryBaseAddress = PageAlignAddress (ResourceHob->PhysicalStart);\r
2327 TestedMemoryLength = PageAlignLength (ResourceHob->PhysicalStart + ResourceHob->ResourceLength - TestedMemoryBaseAddress);\r
2328 if (TestedMemoryLength < MinimalMemorySizeNeeded) {\r
2329 continue;\r
2330 }\r
2331\r
2332 //\r
2333 // Save the range described by the Resource Descriptor that is large enough to initilize the DXE Core\r
2334 //\r
2335 BaseAddress = TestedMemoryBaseAddress;\r
2336 Length = TestedMemoryLength;\r
d1102dba 2337 Attributes = ResourceHob->ResourceAttribute;\r
3a05b131 2338 HighAddress = ResourceHob->PhysicalStart;\r
c4c085a2 2339 }\r
c4c085a2 2340 }\r
28a00297 2341\r
3a05b131
SZ
2342 DEBUG ((EFI_D_INFO, "CoreInitializeMemoryServices:\n"));\r
2343 DEBUG ((EFI_D_INFO, " BaseAddress - 0x%lx Length - 0x%lx MinimalMemorySizeNeeded - 0x%lx\n", BaseAddress, Length, MinimalMemorySizeNeeded));\r
28a00297 2344\r
2345 //\r
2346 // If no memory regions are found that are big enough to initialize the DXE core, then ASSERT().\r
2347 //\r
3a05b131 2348 ASSERT (Length >= MinimalMemorySizeNeeded);\r
28a00297 2349\r
2350 //\r
2351 // Convert the Resource HOB Attributes to an EFI Memory Capabilities mask\r
2352 //\r
74705ca5
SZ
2353 if ((Attributes & EFI_RESOURCE_ATTRIBUTE_MORE_RELIABLE) == EFI_RESOURCE_ATTRIBUTE_MORE_RELIABLE) {\r
2354 Capabilities = CoreConvertResourceDescriptorHobAttributesToCapabilities (EfiGcdMemoryTypeMoreReliable, Attributes);\r
2355 } else {\r
2356 Capabilities = CoreConvertResourceDescriptorHobAttributesToCapabilities (EfiGcdMemoryTypeSystemMemory, Attributes);\r
2357 }\r
28a00297 2358\r
2359 //\r
2360 // Declare the very first memory region, so the EFI Memory Services are available.\r
2361 //\r
2362 CoreAddMemoryDescriptor (\r
2363 EfiConventionalMemory,\r
2364 BaseAddress,\r
2365 RShiftU64 (Length, EFI_PAGE_SHIFT),\r
2366 Capabilities\r
2367 );\r
2368\r
2369 *MemoryBaseAddress = BaseAddress;\r
2370 *MemoryLength = Length;\r
2371\r
2372 return EFI_SUCCESS;\r
2373}\r
2374\r
28a00297 2375\r
162ed594 2376/**\r
2377 External function. Initializes the GCD and memory services based on the memory\r
28a00297 2378 descriptor HOBs. This function is responsible for priming the GCD map and the\r
c18f12d3 2379 memory map, so memory allocations and resource allocations can be made. The\r
2380 HobStart will be relocated to a pool buffer.\r
28a00297 2381\r
022c6d45 2382 @param HobStart The start address of the HOB\r
2383 @param MemoryBaseAddress Start address of memory region found to init DXE\r
2384 core.\r
2385 @param MemoryLength Length of memory region found to init DXE core.\r
28a00297 2386\r
162ed594 2387 @retval EFI_SUCCESS GCD services successfully initialized.\r
28a00297 2388\r
162ed594 2389**/\r
2390EFI_STATUS\r
2391CoreInitializeGcdServices (\r
e94a9ff7 2392 IN OUT VOID **HobStart,\r
162ed594 2393 IN EFI_PHYSICAL_ADDRESS MemoryBaseAddress,\r
2394 IN UINT64 MemoryLength\r
2395 )\r
28a00297 2396{\r
e94a9ff7 2397 EFI_PEI_HOB_POINTERS Hob;\r
28a00297 2398 VOID *NewHobList;\r
e94a9ff7 2399 EFI_HOB_HANDOFF_INFO_TABLE *PhitHob;\r
28a00297 2400 UINT8 SizeOfMemorySpace;\r
2401 UINT8 SizeOfIoSpace;\r
2402 EFI_HOB_RESOURCE_DESCRIPTOR *ResourceHob;\r
2403 EFI_PHYSICAL_ADDRESS BaseAddress;\r
2404 UINT64 Length;\r
2405 EFI_STATUS Status;\r
2406 EFI_GCD_MAP_ENTRY *Entry;\r
2407 EFI_GCD_MEMORY_TYPE GcdMemoryType;\r
2408 EFI_GCD_IO_TYPE GcdIoType;\r
2409 EFI_GCD_MEMORY_SPACE_DESCRIPTOR Descriptor;\r
2410 EFI_HOB_MEMORY_ALLOCATION *MemoryHob;\r
2411 EFI_HOB_FIRMWARE_VOLUME *FirmwareVolumeHob;\r
2412 UINTN NumberOfDescriptors;\r
2413 EFI_GCD_MEMORY_SPACE_DESCRIPTOR *MemorySpaceMap;\r
2414 UINTN Index;\r
2415 UINT64 Capabilities;\r
2416 EFI_HOB_CPU * CpuHob;\r
a46bbdd3 2417 EFI_GCD_MEMORY_SPACE_DESCRIPTOR *MemorySpaceMapHobList;\r
e94a9ff7 2418\r
28a00297 2419 //\r
2420 // Cache the PHIT HOB for later use\r
2421 //\r
2422 PhitHob = (EFI_HOB_HANDOFF_INFO_TABLE *)(*HobStart);\r
2423\r
2424 //\r
2425 // Get the number of address lines in the I/O and Memory space for the CPU\r
2426 //\r
2427 CpuHob = GetFirstHob (EFI_HOB_TYPE_CPU);\r
2428 ASSERT (CpuHob != NULL);\r
2429 SizeOfMemorySpace = CpuHob->SizeOfMemorySpace;\r
2430 SizeOfIoSpace = CpuHob->SizeOfIoSpace;\r
022c6d45 2431\r
28a00297 2432 //\r
2433 // Initialize the GCD Memory Space Map\r
2434 //\r
9c4ac31c 2435 Entry = AllocateCopyPool (sizeof (EFI_GCD_MAP_ENTRY), &mGcdMemorySpaceMapEntryTemplate);\r
28a00297 2436 ASSERT (Entry != NULL);\r
2437\r
2438 Entry->EndAddress = LShiftU64 (1, SizeOfMemorySpace) - 1;\r
2439\r
2440 InsertHeadList (&mGcdMemorySpaceMap, &Entry->Link);\r
2441\r
aa927cae 2442 CoreDumpGcdMemorySpaceMap (TRUE);\r
d1102dba 2443\r
28a00297 2444 //\r
2445 // Initialize the GCD I/O Space Map\r
2446 //\r
9c4ac31c 2447 Entry = AllocateCopyPool (sizeof (EFI_GCD_MAP_ENTRY), &mGcdIoSpaceMapEntryTemplate);\r
28a00297 2448 ASSERT (Entry != NULL);\r
2449\r
2450 Entry->EndAddress = LShiftU64 (1, SizeOfIoSpace) - 1;\r
2451\r
2452 InsertHeadList (&mGcdIoSpaceMap, &Entry->Link);\r
2453\r
aa927cae 2454 CoreDumpGcdIoSpaceMap (TRUE);\r
d1102dba 2455\r
28a00297 2456 //\r
022c6d45 2457 // Walk the HOB list and add all resource descriptors to the GCD\r
28a00297 2458 //\r
2459 for (Hob.Raw = *HobStart; !END_OF_HOB_LIST(Hob); Hob.Raw = GET_NEXT_HOB(Hob)) {\r
2460\r
2461 GcdMemoryType = EfiGcdMemoryTypeNonExistent;\r
2462 GcdIoType = EfiGcdIoTypeNonExistent;\r
2463\r
2464 if (GET_HOB_TYPE (Hob) == EFI_HOB_TYPE_RESOURCE_DESCRIPTOR) {\r
2465\r
2466 ResourceHob = Hob.ResourceDescriptor;\r
2467\r
2468 switch (ResourceHob->ResourceType) {\r
2469 case EFI_RESOURCE_SYSTEM_MEMORY:\r
2470 if ((ResourceHob->ResourceAttribute & MEMORY_ATTRIBUTE_MASK) == TESTED_MEMORY_ATTRIBUTES) {\r
74705ca5
SZ
2471 if ((ResourceHob->ResourceAttribute & EFI_RESOURCE_ATTRIBUTE_MORE_RELIABLE) == EFI_RESOURCE_ATTRIBUTE_MORE_RELIABLE) {\r
2472 GcdMemoryType = EfiGcdMemoryTypeMoreReliable;\r
2473 } else {\r
2474 GcdMemoryType = EfiGcdMemoryTypeSystemMemory;\r
2475 }\r
28a00297 2476 }\r
2477 if ((ResourceHob->ResourceAttribute & MEMORY_ATTRIBUTE_MASK) == INITIALIZED_MEMORY_ATTRIBUTES) {\r
2478 GcdMemoryType = EfiGcdMemoryTypeReserved;\r
2479 }\r
2480 if ((ResourceHob->ResourceAttribute & MEMORY_ATTRIBUTE_MASK) == PRESENT_MEMORY_ATTRIBUTES) {\r
2481 GcdMemoryType = EfiGcdMemoryTypeReserved;\r
2482 }\r
a671a012 2483 if ((ResourceHob->ResourceAttribute & EFI_RESOURCE_ATTRIBUTE_PERSISTENT) == EFI_RESOURCE_ATTRIBUTE_PERSISTENT) {\r
35ac962b 2484 GcdMemoryType = EfiGcdMemoryTypePersistent;\r
a671a012 2485 }\r
28a00297 2486 break;\r
2487 case EFI_RESOURCE_MEMORY_MAPPED_IO:\r
2488 case EFI_RESOURCE_FIRMWARE_DEVICE:\r
2489 GcdMemoryType = EfiGcdMemoryTypeMemoryMappedIo;\r
2490 break;\r
2491 case EFI_RESOURCE_MEMORY_MAPPED_IO_PORT:\r
2492 case EFI_RESOURCE_MEMORY_RESERVED:\r
2493 GcdMemoryType = EfiGcdMemoryTypeReserved;\r
2494 break;\r
2495 case EFI_RESOURCE_IO:\r
2496 GcdIoType = EfiGcdIoTypeIo;\r
2497 break;\r
2498 case EFI_RESOURCE_IO_RESERVED:\r
2499 GcdIoType = EfiGcdIoTypeReserved;\r
2500 break;\r
2501 }\r
2502\r
2503 if (GcdMemoryType != EfiGcdMemoryTypeNonExistent) {\r
d12a2ecb 2504 //\r
2505 // Validate the Resource HOB Attributes\r
2506 //\r
2507 CoreValidateResourceDescriptorHobAttributes (ResourceHob->ResourceAttribute);\r
2508\r
28a00297 2509 //\r
2510 // Convert the Resource HOB Attributes to an EFI Memory Capabilities mask\r
2511 //\r
2512 Capabilities = CoreConvertResourceDescriptorHobAttributesToCapabilities (\r
2513 GcdMemoryType,\r
2514 ResourceHob->ResourceAttribute\r
2515 );\r
2516\r
2517 Status = CoreInternalAddMemorySpace (\r
2518 GcdMemoryType,\r
2519 ResourceHob->PhysicalStart,\r
2520 ResourceHob->ResourceLength,\r
2521 Capabilities\r
2522 );\r
2523 }\r
2524\r
2525 if (GcdIoType != EfiGcdIoTypeNonExistent) {\r
2526 Status = CoreAddIoSpace (\r
2527 GcdIoType,\r
2528 ResourceHob->PhysicalStart,\r
2529 ResourceHob->ResourceLength\r
2530 );\r
2531 }\r
2532 }\r
2533 }\r
2534\r
2535 //\r
2536 // Allocate first memory region from the GCD by the DXE core\r
2537 //\r
74705ca5
SZ
2538 Status = CoreGetMemorySpaceDescriptor (MemoryBaseAddress, &Descriptor);\r
2539 if (!EFI_ERROR (Status)) {\r
2540 ASSERT ((Descriptor.GcdMemoryType == EfiGcdMemoryTypeSystemMemory) ||\r
2541 (Descriptor.GcdMemoryType == EfiGcdMemoryTypeMoreReliable));\r
2542 Status = CoreAllocateMemorySpace (\r
2543 EfiGcdAllocateAddress,\r
2544 Descriptor.GcdMemoryType,\r
2545 0,\r
2546 MemoryLength,\r
2547 &MemoryBaseAddress,\r
2548 gDxeCoreImageHandle,\r
2549 NULL\r
2550 );\r
2551 }\r
28a00297 2552\r
2553 //\r
2554 // Walk the HOB list and allocate all memory space that is consumed by memory allocation HOBs,\r
2555 // and Firmware Volume HOBs. Also update the EFI Memory Map with the memory allocation HOBs.\r
2556 //\r
2557 for (Hob.Raw = *HobStart; !END_OF_HOB_LIST(Hob); Hob.Raw = GET_NEXT_HOB(Hob)) {\r
2558 if (GET_HOB_TYPE (Hob) == EFI_HOB_TYPE_MEMORY_ALLOCATION) {\r
2559 MemoryHob = Hob.MemoryAllocation;\r
2560 BaseAddress = MemoryHob->AllocDescriptor.MemoryBaseAddress;\r
f942f107 2561 Status = CoreGetMemorySpaceDescriptor (BaseAddress, &Descriptor);\r
28a00297 2562 if (!EFI_ERROR (Status)) {\r
f942f107 2563 Status = CoreAllocateMemorySpace (\r
2564 EfiGcdAllocateAddress,\r
022c6d45 2565 Descriptor.GcdMemoryType,\r
f942f107 2566 0,\r
2567 MemoryHob->AllocDescriptor.MemoryLength,\r
2568 &BaseAddress,\r
2569 gDxeCoreImageHandle,\r
2570 NULL\r
2571 );\r
74705ca5
SZ
2572 if (!EFI_ERROR (Status) &&\r
2573 ((Descriptor.GcdMemoryType == EfiGcdMemoryTypeSystemMemory) ||\r
2574 (Descriptor.GcdMemoryType == EfiGcdMemoryTypeMoreReliable))) {\r
28a00297 2575 CoreAddMemoryDescriptor (\r
2576 MemoryHob->AllocDescriptor.MemoryType,\r
2577 MemoryHob->AllocDescriptor.MemoryBaseAddress,\r
2578 RShiftU64 (MemoryHob->AllocDescriptor.MemoryLength, EFI_PAGE_SHIFT),\r
2579 Descriptor.Capabilities & (~EFI_MEMORY_RUNTIME)\r
2580 );\r
2581 }\r
2582 }\r
2583 }\r
2584\r
2585 if (GET_HOB_TYPE (Hob) == EFI_HOB_TYPE_FV) {\r
2586 FirmwareVolumeHob = Hob.FirmwareVolume;\r
2587 BaseAddress = FirmwareVolumeHob->BaseAddress;\r
2588 Status = CoreAllocateMemorySpace (\r
2589 EfiGcdAllocateAddress,\r
022c6d45 2590 EfiGcdMemoryTypeMemoryMappedIo,\r
28a00297 2591 0,\r
2592 FirmwareVolumeHob->Length,\r
2593 &BaseAddress,\r
2594 gDxeCoreImageHandle,\r
2595 NULL\r
2596 );\r
2597 }\r
2598 }\r
2599\r
28a00297 2600 //\r
2601 // Add and allocate the remaining unallocated system memory to the memory services.\r
2602 //\r
2603 Status = CoreGetMemorySpaceMap (&NumberOfDescriptors, &MemorySpaceMap);\r
311a71b2 2604 ASSERT (Status == EFI_SUCCESS);\r
2605\r
a46bbdd3 2606 MemorySpaceMapHobList = NULL;\r
28a00297 2607 for (Index = 0; Index < NumberOfDescriptors; Index++) {\r
74705ca5
SZ
2608 if ((MemorySpaceMap[Index].GcdMemoryType == EfiGcdMemoryTypeSystemMemory) ||\r
2609 (MemorySpaceMap[Index].GcdMemoryType == EfiGcdMemoryTypeMoreReliable)) {\r
28a00297 2610 if (MemorySpaceMap[Index].ImageHandle == NULL) {\r
2611 BaseAddress = PageAlignAddress (MemorySpaceMap[Index].BaseAddress);\r
2612 Length = PageAlignLength (MemorySpaceMap[Index].BaseAddress + MemorySpaceMap[Index].Length - BaseAddress);\r
383c303c 2613 if (Length == 0 || MemorySpaceMap[Index].BaseAddress + MemorySpaceMap[Index].Length < BaseAddress) {\r
2614 continue;\r
2615 }\r
a46bbdd3
SZ
2616 if (((UINTN) MemorySpaceMap[Index].BaseAddress <= (UINTN) (*HobStart)) &&\r
2617 ((UINTN) (MemorySpaceMap[Index].BaseAddress + MemorySpaceMap[Index].Length) >= (UINTN) PhitHob->EfiFreeMemoryBottom)) {\r
2618 //\r
2619 // Skip the memory space that covers HOB List, it should be processed\r
2620 // after HOB List relocation to avoid the resources allocated by others\r
2621 // to corrupt HOB List before its relocation.\r
2622 //\r
2623 MemorySpaceMapHobList = &MemorySpaceMap[Index];\r
2624 continue;\r
2625 }\r
28a00297 2626 CoreAddMemoryDescriptor (\r
2627 EfiConventionalMemory,\r
2628 BaseAddress,\r
2629 RShiftU64 (Length, EFI_PAGE_SHIFT),\r
2630 MemorySpaceMap[Index].Capabilities & (~EFI_MEMORY_RUNTIME)\r
2631 );\r
2632 Status = CoreAllocateMemorySpace (\r
2633 EfiGcdAllocateAddress,\r
74705ca5 2634 MemorySpaceMap[Index].GcdMemoryType,\r
28a00297 2635 0,\r
2636 Length,\r
2637 &BaseAddress,\r
2638 gDxeCoreImageHandle,\r
2639 NULL\r
2640 );\r
2641 }\r
2642 }\r
2643 }\r
a46bbdd3
SZ
2644\r
2645 //\r
2646 // Relocate HOB List to an allocated pool buffer.\r
2647 // The relocation should be at after all the tested memory resources added\r
2648 // (except the memory space that covers HOB List) to the memory services,\r
2649 // because the memory resource found in CoreInitializeMemoryServices()\r
2650 // may have not enough remaining resource for HOB List.\r
2651 //\r
2652 NewHobList = AllocateCopyPool (\r
2653 (UINTN) PhitHob->EfiFreeMemoryBottom - (UINTN) (*HobStart),\r
2654 *HobStart\r
2655 );\r
2656 ASSERT (NewHobList != NULL);\r
2657\r
2658 *HobStart = NewHobList;\r
2659 gHobList = NewHobList;\r
2660\r
2661 if (MemorySpaceMapHobList != NULL) {\r
2662 //\r
2663 // Add and allocate the memory space that covers HOB List to the memory services\r
2664 // after HOB List relocation.\r
2665 //\r
2666 BaseAddress = PageAlignAddress (MemorySpaceMapHobList->BaseAddress);\r
2667 Length = PageAlignLength (MemorySpaceMapHobList->BaseAddress + MemorySpaceMapHobList->Length - BaseAddress);\r
2668 CoreAddMemoryDescriptor (\r
2669 EfiConventionalMemory,\r
2670 BaseAddress,\r
2671 RShiftU64 (Length, EFI_PAGE_SHIFT),\r
2672 MemorySpaceMapHobList->Capabilities & (~EFI_MEMORY_RUNTIME)\r
2673 );\r
2674 Status = CoreAllocateMemorySpace (\r
2675 EfiGcdAllocateAddress,\r
2676 MemorySpaceMapHobList->GcdMemoryType,\r
2677 0,\r
2678 Length,\r
2679 &BaseAddress,\r
2680 gDxeCoreImageHandle,\r
2681 NULL\r
2682 );\r
2683 }\r
2684\r
28a00297 2685 CoreFreePool (MemorySpaceMap);\r
2686\r
2687 return EFI_SUCCESS;\r
2688}\r