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