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