2 The file contains the GCD related services in the EFI Boot Services Table.
3 The GCD services are used to manage the memory and I/O regions that
4 are accessible to the CPU that is executing the DXE core.
6 Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
7 SPDX-License-Identifier: BSD-2-Clause-Patent
13 #include "Mem/HeapGuard.h"
15 #define MINIMUM_INITIAL_MEMORY_SIZE 0x10000
17 #define MEMORY_ATTRIBUTE_MASK (EFI_RESOURCE_ATTRIBUTE_PRESENT | \
18 EFI_RESOURCE_ATTRIBUTE_INITIALIZED | \
19 EFI_RESOURCE_ATTRIBUTE_TESTED | \
20 EFI_RESOURCE_ATTRIBUTE_READ_PROTECTED | \
21 EFI_RESOURCE_ATTRIBUTE_WRITE_PROTECTED | \
22 EFI_RESOURCE_ATTRIBUTE_EXECUTION_PROTECTED | \
23 EFI_RESOURCE_ATTRIBUTE_READ_ONLY_PROTECTED | \
24 EFI_RESOURCE_ATTRIBUTE_16_BIT_IO | \
25 EFI_RESOURCE_ATTRIBUTE_32_BIT_IO | \
26 EFI_RESOURCE_ATTRIBUTE_64_BIT_IO | \
27 EFI_RESOURCE_ATTRIBUTE_PERSISTENT )
29 #define TESTED_MEMORY_ATTRIBUTES (EFI_RESOURCE_ATTRIBUTE_PRESENT | \
30 EFI_RESOURCE_ATTRIBUTE_INITIALIZED | \
31 EFI_RESOURCE_ATTRIBUTE_TESTED )
33 #define INITIALIZED_MEMORY_ATTRIBUTES (EFI_RESOURCE_ATTRIBUTE_PRESENT | \
34 EFI_RESOURCE_ATTRIBUTE_INITIALIZED )
36 #define PRESENT_MEMORY_ATTRIBUTES (EFI_RESOURCE_ATTRIBUTE_PRESENT)
41 EFI_LOCK mGcdMemorySpaceLock
= EFI_INITIALIZE_LOCK_VARIABLE (TPL_NOTIFY
);
42 EFI_LOCK mGcdIoSpaceLock
= EFI_INITIALIZE_LOCK_VARIABLE (TPL_NOTIFY
);
43 LIST_ENTRY mGcdMemorySpaceMap
= INITIALIZE_LIST_HEAD_VARIABLE (mGcdMemorySpaceMap
);
44 LIST_ENTRY mGcdIoSpaceMap
= INITIALIZE_LIST_HEAD_VARIABLE (mGcdIoSpaceMap
);
46 EFI_GCD_MAP_ENTRY mGcdMemorySpaceMapEntryTemplate
= {
47 EFI_GCD_MAP_SIGNATURE
,
56 EfiGcdMemoryTypeNonExistent
,
62 EFI_GCD_MAP_ENTRY mGcdIoSpaceMapEntryTemplate
= {
63 EFI_GCD_MAP_SIGNATURE
,
72 (EFI_GCD_MEMORY_TYPE
) 0,
73 EfiGcdIoTypeNonExistent
,
78 GCD_ATTRIBUTE_CONVERSION_ENTRY mAttributeConversionTable
[] = {
79 { EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE
, EFI_MEMORY_UC
, TRUE
},
80 { EFI_RESOURCE_ATTRIBUTE_UNCACHED_EXPORTED
, EFI_MEMORY_UCE
, TRUE
},
81 { EFI_RESOURCE_ATTRIBUTE_WRITE_COMBINEABLE
, EFI_MEMORY_WC
, TRUE
},
82 { EFI_RESOURCE_ATTRIBUTE_WRITE_THROUGH_CACHEABLE
, EFI_MEMORY_WT
, TRUE
},
83 { EFI_RESOURCE_ATTRIBUTE_WRITE_BACK_CACHEABLE
, EFI_MEMORY_WB
, TRUE
},
84 { EFI_RESOURCE_ATTRIBUTE_READ_PROTECTABLE
, EFI_MEMORY_RP
, TRUE
},
85 { EFI_RESOURCE_ATTRIBUTE_WRITE_PROTECTABLE
, EFI_MEMORY_WP
, TRUE
},
86 { EFI_RESOURCE_ATTRIBUTE_EXECUTION_PROTECTABLE
, EFI_MEMORY_XP
, TRUE
},
87 { EFI_RESOURCE_ATTRIBUTE_READ_ONLY_PROTECTABLE
, EFI_MEMORY_RO
, TRUE
},
88 { EFI_RESOURCE_ATTRIBUTE_PRESENT
, EFI_MEMORY_PRESENT
, FALSE
},
89 { EFI_RESOURCE_ATTRIBUTE_INITIALIZED
, EFI_MEMORY_INITIALIZED
, FALSE
},
90 { EFI_RESOURCE_ATTRIBUTE_TESTED
, EFI_MEMORY_TESTED
, FALSE
},
91 { EFI_RESOURCE_ATTRIBUTE_PERSISTABLE
, EFI_MEMORY_NV
, TRUE
},
92 { EFI_RESOURCE_ATTRIBUTE_MORE_RELIABLE
, EFI_MEMORY_MORE_RELIABLE
, TRUE
},
97 /// Lookup table used to print GCD Memory Space Map
99 GLOBAL_REMOVE_IF_UNREFERENCED CONST CHAR8
*mGcdMemoryTypeNames
[] = {
100 "NonExist ", // EfiGcdMemoryTypeNonExistent
101 "Reserved ", // EfiGcdMemoryTypeReserved
102 "SystemMem", // EfiGcdMemoryTypeSystemMemory
103 "MMIO ", // EfiGcdMemoryTypeMemoryMappedIo
104 "PersisMem", // EfiGcdMemoryTypePersistent
105 "MoreRelia", // EfiGcdMemoryTypeMoreReliable
106 "Unknown " // EfiGcdMemoryTypeMaximum
110 /// Lookup table used to print GCD I/O Space Map
112 GLOBAL_REMOVE_IF_UNREFERENCED CONST CHAR8
*mGcdIoTypeNames
[] = {
113 "NonExist", // EfiGcdIoTypeNonExistent
114 "Reserved", // EfiGcdIoTypeReserved
115 "I/O ", // EfiGcdIoTypeIo
116 "Unknown " // EfiGcdIoTypeMaximum
120 /// Lookup table used to print GCD Allocation Types
122 GLOBAL_REMOVE_IF_UNREFERENCED CONST CHAR8
*mGcdAllocationTypeNames
[] = {
123 "AnySearchBottomUp ", // EfiGcdAllocateAnySearchBottomUp
124 "MaxAddressSearchBottomUp ", // EfiGcdAllocateMaxAddressSearchBottomUp
125 "AtAddress ", // EfiGcdAllocateAddress
126 "AnySearchTopDown ", // EfiGcdAllocateAnySearchTopDown
127 "MaxAddressSearchTopDown ", // EfiGcdAllocateMaxAddressSearchTopDown
128 "Unknown " // EfiGcdMaxAllocateType
132 Dump the entire contents if the GCD Memory Space Map using DEBUG() macros when
133 PcdDebugPrintErrorLevel has the DEBUG_GCD bit set.
135 @param InitialMap TRUE if the initial GCD Memory Map is being dumped. Otherwise, FALSE.
140 CoreDumpGcdMemorySpaceMap (
146 UINTN NumberOfDescriptors
;
147 EFI_GCD_MEMORY_SPACE_DESCRIPTOR
*MemorySpaceMap
;
150 Status
= CoreGetMemorySpaceMap (&NumberOfDescriptors
, &MemorySpaceMap
);
151 ASSERT (Status
== EFI_SUCCESS
&& MemorySpaceMap
!= NULL
);
154 DEBUG ((DEBUG_GCD
, "GCD:Initial GCD Memory Space Map\n"));
156 DEBUG ((DEBUG_GCD
, "GCDMemType Range Capabilities Attributes \n"));
157 DEBUG ((DEBUG_GCD
, "========== ================================= ================ ================\n"));
158 for (Index
= 0; Index
< NumberOfDescriptors
; Index
++) {
159 DEBUG ((DEBUG_GCD
, "%a %016lx-%016lx %016lx %016lx%c\n",
160 mGcdMemoryTypeNames
[MIN (MemorySpaceMap
[Index
].GcdMemoryType
, EfiGcdMemoryTypeMaximum
)],
161 MemorySpaceMap
[Index
].BaseAddress
,
162 MemorySpaceMap
[Index
].BaseAddress
+ MemorySpaceMap
[Index
].Length
- 1,
163 MemorySpaceMap
[Index
].Capabilities
,
164 MemorySpaceMap
[Index
].Attributes
,
165 MemorySpaceMap
[Index
].ImageHandle
== NULL
? ' ' : '*'
168 DEBUG ((DEBUG_GCD
, "\n"));
169 FreePool (MemorySpaceMap
);
174 Dump the entire contents if the GCD I/O Space Map using DEBUG() macros when
175 PcdDebugPrintErrorLevel has the DEBUG_GCD bit set.
177 @param InitialMap TRUE if the initial GCD I/O Map is being dumped. Otherwise, FALSE.
182 CoreDumpGcdIoSpaceMap (
188 UINTN NumberOfDescriptors
;
189 EFI_GCD_IO_SPACE_DESCRIPTOR
*IoSpaceMap
;
192 Status
= CoreGetIoSpaceMap (&NumberOfDescriptors
, &IoSpaceMap
);
193 ASSERT (Status
== EFI_SUCCESS
&& IoSpaceMap
!= NULL
);
196 DEBUG ((DEBUG_GCD
, "GCD:Initial GCD I/O Space Map\n"));
199 DEBUG ((DEBUG_GCD
, "GCDIoType Range \n"));
200 DEBUG ((DEBUG_GCD
, "========== =================================\n"));
201 for (Index
= 0; Index
< NumberOfDescriptors
; Index
++) {
202 DEBUG ((DEBUG_GCD
, "%a %016lx-%016lx%c\n",
203 mGcdIoTypeNames
[MIN (IoSpaceMap
[Index
].GcdIoType
, EfiGcdIoTypeMaximum
)],
204 IoSpaceMap
[Index
].BaseAddress
,
205 IoSpaceMap
[Index
].BaseAddress
+ IoSpaceMap
[Index
].Length
- 1,
206 IoSpaceMap
[Index
].ImageHandle
== NULL
? ' ' : '*'
209 DEBUG ((DEBUG_GCD
, "\n"));
210 FreePool (IoSpaceMap
);
215 Validate resource descriptor HOB's attributes.
217 If Attributes includes some memory resource's settings, it should include
218 the corresponding capabilites also.
220 @param Attributes Resource descriptor HOB attributes.
224 CoreValidateResourceDescriptorHobAttributes (
228 ASSERT (((Attributes
& EFI_RESOURCE_ATTRIBUTE_READ_PROTECTED
) == 0) ||
229 ((Attributes
& EFI_RESOURCE_ATTRIBUTE_READ_PROTECTABLE
) != 0));
230 ASSERT (((Attributes
& EFI_RESOURCE_ATTRIBUTE_WRITE_PROTECTED
) == 0) ||
231 ((Attributes
& EFI_RESOURCE_ATTRIBUTE_WRITE_PROTECTABLE
) != 0));
232 ASSERT (((Attributes
& EFI_RESOURCE_ATTRIBUTE_EXECUTION_PROTECTED
) == 0) ||
233 ((Attributes
& EFI_RESOURCE_ATTRIBUTE_EXECUTION_PROTECTABLE
) != 0));
234 ASSERT (((Attributes
& EFI_RESOURCE_ATTRIBUTE_READ_ONLY_PROTECTED
) == 0) ||
235 ((Attributes
& EFI_RESOURCE_ATTRIBUTE_READ_ONLY_PROTECTABLE
) != 0));
236 ASSERT (((Attributes
& EFI_RESOURCE_ATTRIBUTE_PERSISTENT
) == 0) ||
237 ((Attributes
& EFI_RESOURCE_ATTRIBUTE_PERSISTABLE
) != 0));
241 Acquire memory lock on mGcdMemorySpaceLock.
245 CoreAcquireGcdMemoryLock (
249 CoreAcquireLock (&mGcdMemorySpaceLock
);
255 Release memory lock on mGcdMemorySpaceLock.
259 CoreReleaseGcdMemoryLock (
263 CoreReleaseLock (&mGcdMemorySpaceLock
);
269 Acquire memory lock on mGcdIoSpaceLock.
273 CoreAcquireGcdIoLock (
277 CoreAcquireLock (&mGcdIoSpaceLock
);
282 Release memory lock on mGcdIoSpaceLock.
286 CoreReleaseGcdIoLock (
290 CoreReleaseLock (&mGcdIoSpaceLock
);
296 // GCD Initialization Worker Functions
299 Aligns a value to the specified boundary.
301 @param Value 64 bit value to align
302 @param Alignment Log base 2 of the boundary to align Value to
303 @param RoundUp TRUE if Value is to be rounded up to the nearest
304 aligned boundary. FALSE is Value is to be
305 rounded down to the nearest aligned boundary.
307 @return A 64 bit value is the aligned to the value nearest Value with an alignment by Alignment.
317 UINT64 AlignmentMask
;
319 AlignmentMask
= LShiftU64 (1, Alignment
) - 1;
321 Value
+= AlignmentMask
;
323 return Value
& (~AlignmentMask
);
328 Aligns address to the page boundary.
330 @param Value 64 bit address to align
332 @return A 64 bit value is the aligned to the value nearest Value with an alignment by Alignment.
340 return AlignValue (Value
, EFI_PAGE_SHIFT
, TRUE
);
345 Aligns length to the page boundary.
347 @param Value 64 bit length to align
349 @return A 64 bit value is the aligned to the value nearest Value with an alignment by Alignment.
357 return AlignValue (Value
, EFI_PAGE_SHIFT
, FALSE
);
361 // GCD Memory Space Worker Functions
365 Allocate pool for two entries.
367 @param TopEntry An entry of GCD map
368 @param BottomEntry An entry of GCD map
370 @retval EFI_OUT_OF_RESOURCES No enough buffer to be allocated.
371 @retval EFI_SUCCESS Both entries successfully allocated.
375 CoreAllocateGcdMapEntry (
376 IN OUT EFI_GCD_MAP_ENTRY
**TopEntry
,
377 IN OUT EFI_GCD_MAP_ENTRY
**BottomEntry
381 // Set to mOnGuarding to TRUE before memory allocation. This will make sure
382 // that the entry memory is not "guarded" by HeapGuard. Otherwise it might
383 // cause problem when it's freed (if HeapGuard is enabled).
386 *TopEntry
= AllocateZeroPool (sizeof (EFI_GCD_MAP_ENTRY
));
388 if (*TopEntry
== NULL
) {
389 return EFI_OUT_OF_RESOURCES
;
393 *BottomEntry
= AllocateZeroPool (sizeof (EFI_GCD_MAP_ENTRY
));
395 if (*BottomEntry
== NULL
) {
396 CoreFreePool (*TopEntry
);
397 return EFI_OUT_OF_RESOURCES
;
405 Internal function. Inserts a new descriptor into a sorted list
407 @param Link The linked list to insert the range BaseAddress
409 @param Entry A pointer to the entry that is inserted
410 @param BaseAddress The base address of the new range
411 @param Length The length of the new range in bytes
412 @param TopEntry Top pad entry to insert if needed.
413 @param BottomEntry Bottom pad entry to insert if needed.
415 @retval EFI_SUCCESS The new range was inserted into the linked list
419 CoreInsertGcdMapEntry (
421 IN EFI_GCD_MAP_ENTRY
*Entry
,
422 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
424 IN EFI_GCD_MAP_ENTRY
*TopEntry
,
425 IN EFI_GCD_MAP_ENTRY
*BottomEntry
428 ASSERT (Length
!= 0);
430 if (BaseAddress
> Entry
->BaseAddress
) {
431 ASSERT (BottomEntry
->Signature
== 0);
433 CopyMem (BottomEntry
, Entry
, sizeof (EFI_GCD_MAP_ENTRY
));
434 Entry
->BaseAddress
= BaseAddress
;
435 BottomEntry
->EndAddress
= BaseAddress
- 1;
436 InsertTailList (Link
, &BottomEntry
->Link
);
439 if ((BaseAddress
+ Length
- 1) < Entry
->EndAddress
) {
440 ASSERT (TopEntry
->Signature
== 0);
442 CopyMem (TopEntry
, Entry
, sizeof (EFI_GCD_MAP_ENTRY
));
443 TopEntry
->BaseAddress
= BaseAddress
+ Length
;
444 Entry
->EndAddress
= BaseAddress
+ Length
- 1;
445 InsertHeadList (Link
, &TopEntry
->Link
);
453 Merge the Gcd region specified by Link and its adjacent entry.
455 @param Link Specify the entry to be merged (with its
457 @param Forward Direction (forward or backward).
460 @retval EFI_SUCCESS Successfully returned.
461 @retval EFI_UNSUPPORTED These adjacent regions could not merge.
465 CoreMergeGcdMapEntry (
471 LIST_ENTRY
*AdjacentLink
;
472 EFI_GCD_MAP_ENTRY
*Entry
;
473 EFI_GCD_MAP_ENTRY
*AdjacentEntry
;
476 // Get adjacent entry
479 AdjacentLink
= Link
->ForwardLink
;
481 AdjacentLink
= Link
->BackLink
;
485 // If AdjacentLink is the head of the list, then no merge can be performed
487 if (AdjacentLink
== Map
) {
491 Entry
= CR (Link
, EFI_GCD_MAP_ENTRY
, Link
, EFI_GCD_MAP_SIGNATURE
);
492 AdjacentEntry
= CR (AdjacentLink
, EFI_GCD_MAP_ENTRY
, Link
, EFI_GCD_MAP_SIGNATURE
);
494 if (Entry
->Capabilities
!= AdjacentEntry
->Capabilities
) {
495 return EFI_UNSUPPORTED
;
497 if (Entry
->Attributes
!= AdjacentEntry
->Attributes
) {
498 return EFI_UNSUPPORTED
;
500 if (Entry
->GcdMemoryType
!= AdjacentEntry
->GcdMemoryType
) {
501 return EFI_UNSUPPORTED
;
503 if (Entry
->GcdIoType
!= AdjacentEntry
->GcdIoType
) {
504 return EFI_UNSUPPORTED
;
506 if (Entry
->ImageHandle
!= AdjacentEntry
->ImageHandle
) {
507 return EFI_UNSUPPORTED
;
509 if (Entry
->DeviceHandle
!= AdjacentEntry
->DeviceHandle
) {
510 return EFI_UNSUPPORTED
;
514 Entry
->EndAddress
= AdjacentEntry
->EndAddress
;
516 Entry
->BaseAddress
= AdjacentEntry
->BaseAddress
;
518 RemoveEntryList (AdjacentLink
);
519 CoreFreePool (AdjacentEntry
);
526 Merge adjacent entries on total chain.
528 @param TopEntry Top entry of GCD map.
529 @param BottomEntry Bottom entry of GCD map.
530 @param StartLink Start link of the list for this loop.
531 @param EndLink End link of the list for this loop.
534 @retval EFI_SUCCESS GCD map successfully cleaned up.
538 CoreCleanupGcdMapEntry (
539 IN EFI_GCD_MAP_ENTRY
*TopEntry
,
540 IN EFI_GCD_MAP_ENTRY
*BottomEntry
,
541 IN LIST_ENTRY
*StartLink
,
542 IN LIST_ENTRY
*EndLink
,
548 if (TopEntry
->Signature
== 0) {
549 CoreFreePool (TopEntry
);
551 if (BottomEntry
->Signature
== 0) {
552 CoreFreePool (BottomEntry
);
556 while (Link
!= EndLink
->ForwardLink
) {
557 CoreMergeGcdMapEntry (Link
, FALSE
, Map
);
558 Link
= Link
->ForwardLink
;
560 CoreMergeGcdMapEntry (EndLink
, TRUE
, Map
);
567 Search a segment of memory space in GCD map. The result is a range of GCD entry list.
569 @param BaseAddress The start address of the segment.
570 @param Length The length of the segment.
571 @param StartLink The first GCD entry involves this segment of
573 @param EndLink The first GCD entry involves this segment of
575 @param Map Points to the start entry to search.
577 @retval EFI_SUCCESS Successfully found the entry.
578 @retval EFI_NOT_FOUND Not found.
582 CoreSearchGcdMapEntry (
583 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
585 OUT LIST_ENTRY
**StartLink
,
586 OUT LIST_ENTRY
**EndLink
,
591 EFI_GCD_MAP_ENTRY
*Entry
;
593 ASSERT (Length
!= 0);
598 Link
= Map
->ForwardLink
;
599 while (Link
!= Map
) {
600 Entry
= CR (Link
, EFI_GCD_MAP_ENTRY
, Link
, EFI_GCD_MAP_SIGNATURE
);
601 if (BaseAddress
>= Entry
->BaseAddress
&& BaseAddress
<= Entry
->EndAddress
) {
604 if (*StartLink
!= NULL
) {
605 if ((BaseAddress
+ Length
- 1) >= Entry
->BaseAddress
&&
606 (BaseAddress
+ Length
- 1) <= Entry
->EndAddress
) {
611 Link
= Link
->ForwardLink
;
614 return EFI_NOT_FOUND
;
619 Count the amount of GCD map entries.
621 @param Map Points to the start entry to do the count loop.
627 CoreCountGcdMapEntry (
635 Link
= Map
->ForwardLink
;
636 while (Link
!= Map
) {
638 Link
= Link
->ForwardLink
;
647 Return the memory attribute specified by Attributes
649 @param Attributes A num with some attribute bits on.
651 @return The enum value of memory attribute.
655 ConverToCpuArchAttributes (
659 UINT64 CpuArchAttributes
;
661 CpuArchAttributes
= Attributes
& EFI_MEMORY_ATTRIBUTE_MASK
;
663 if ( (Attributes
& EFI_MEMORY_UC
) == EFI_MEMORY_UC
) {
664 CpuArchAttributes
|= EFI_MEMORY_UC
;
665 } else if ( (Attributes
& EFI_MEMORY_WC
) == EFI_MEMORY_WC
) {
666 CpuArchAttributes
|= EFI_MEMORY_WC
;
667 } else if ( (Attributes
& EFI_MEMORY_WT
) == EFI_MEMORY_WT
) {
668 CpuArchAttributes
|= EFI_MEMORY_WT
;
669 } else if ( (Attributes
& EFI_MEMORY_WB
) == EFI_MEMORY_WB
) {
670 CpuArchAttributes
|= EFI_MEMORY_WB
;
671 } else if ( (Attributes
& EFI_MEMORY_UCE
) == EFI_MEMORY_UCE
) {
672 CpuArchAttributes
|= EFI_MEMORY_UCE
;
673 } else if ( (Attributes
& EFI_MEMORY_WP
) == EFI_MEMORY_WP
) {
674 CpuArchAttributes
|= EFI_MEMORY_WP
;
677 return CpuArchAttributes
;
682 Do operation on a segment of memory space specified (add, free, remove, change attribute ...).
684 @param Operation The type of the operation
685 @param GcdMemoryType Additional information for the operation
686 @param GcdIoType Additional information for the operation
687 @param BaseAddress Start address of the segment
688 @param Length length of the segment
689 @param Capabilities The alterable attributes of a newly added entry
690 @param Attributes The attributes needs to be set
692 @retval EFI_INVALID_PARAMETER Length is 0 or address (length) not aligned when
694 @retval EFI_SUCCESS Action successfully done.
695 @retval EFI_UNSUPPORTED Could not find the proper descriptor on this
696 segment or set an upsupported attribute.
697 @retval EFI_ACCESS_DENIED Operate on an space non-exist or is used for an
699 @retval EFI_NOT_FOUND Free a non-using space or remove a non-exist
701 @retval EFI_OUT_OF_RESOURCES No buffer could be allocated.
702 @retval EFI_NOT_AVAILABLE_YET The attributes cannot be set because CPU architectural protocol
703 is not available yet.
708 IN EFI_GCD_MEMORY_TYPE GcdMemoryType
,
709 IN EFI_GCD_IO_TYPE GcdIoType
,
710 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
712 IN UINT64 Capabilities
,
719 EFI_GCD_MAP_ENTRY
*Entry
;
720 EFI_GCD_MAP_ENTRY
*TopEntry
;
721 EFI_GCD_MAP_ENTRY
*BottomEntry
;
722 LIST_ENTRY
*StartLink
;
724 UINT64 CpuArchAttributes
;
727 DEBUG ((DEBUG_GCD
, " Status = %r\n", EFI_INVALID_PARAMETER
));
728 return EFI_INVALID_PARAMETER
;
732 if ((Operation
& GCD_MEMORY_SPACE_OPERATION
) != 0) {
733 CoreAcquireGcdMemoryLock ();
734 Map
= &mGcdMemorySpaceMap
;
735 } else if ((Operation
& GCD_IO_SPACE_OPERATION
) != 0) {
736 CoreAcquireGcdIoLock ();
737 Map
= &mGcdIoSpaceMap
;
743 // Search for the list of descriptors that cover the range BaseAddress to BaseAddress+Length
745 Status
= CoreSearchGcdMapEntry (BaseAddress
, Length
, &StartLink
, &EndLink
, Map
);
746 if (EFI_ERROR (Status
)) {
747 Status
= EFI_UNSUPPORTED
;
751 ASSERT (StartLink
!= NULL
&& EndLink
!= NULL
);
754 // Verify that the list of descriptors are unallocated non-existent memory.
757 while (Link
!= EndLink
->ForwardLink
) {
758 Entry
= CR (Link
, EFI_GCD_MAP_ENTRY
, Link
, EFI_GCD_MAP_SIGNATURE
);
763 case GCD_ADD_MEMORY_OPERATION
:
764 if (Entry
->GcdMemoryType
!= EfiGcdMemoryTypeNonExistent
||
765 Entry
->ImageHandle
!= NULL
) {
766 Status
= EFI_ACCESS_DENIED
;
770 case GCD_ADD_IO_OPERATION
:
771 if (Entry
->GcdIoType
!= EfiGcdIoTypeNonExistent
||
772 Entry
->ImageHandle
!= NULL
) {
773 Status
= EFI_ACCESS_DENIED
;
780 case GCD_FREE_MEMORY_OPERATION
:
781 case GCD_FREE_IO_OPERATION
:
782 if (Entry
->ImageHandle
== NULL
) {
783 Status
= EFI_NOT_FOUND
;
790 case GCD_REMOVE_MEMORY_OPERATION
:
791 if (Entry
->GcdMemoryType
== EfiGcdMemoryTypeNonExistent
) {
792 Status
= EFI_NOT_FOUND
;
795 if (Entry
->ImageHandle
!= NULL
) {
796 Status
= EFI_ACCESS_DENIED
;
800 case GCD_REMOVE_IO_OPERATION
:
801 if (Entry
->GcdIoType
== EfiGcdIoTypeNonExistent
) {
802 Status
= EFI_NOT_FOUND
;
805 if (Entry
->ImageHandle
!= NULL
) {
806 Status
= EFI_ACCESS_DENIED
;
811 // Set attributes operation
813 case GCD_SET_ATTRIBUTES_MEMORY_OPERATION
:
814 if ((Attributes
& EFI_MEMORY_RUNTIME
) != 0) {
815 if ((BaseAddress
& EFI_PAGE_MASK
) != 0 || (Length
& EFI_PAGE_MASK
) != 0) {
816 Status
= EFI_INVALID_PARAMETER
;
820 if ((Entry
->Capabilities
& Attributes
) != Attributes
) {
821 Status
= EFI_UNSUPPORTED
;
826 // Set capabilities operation
828 case GCD_SET_CAPABILITIES_MEMORY_OPERATION
:
829 if ((BaseAddress
& EFI_PAGE_MASK
) != 0 || (Length
& EFI_PAGE_MASK
) != 0) {
830 Status
= EFI_INVALID_PARAMETER
;
835 // Current attributes must still be supported with new capabilities
837 if ((Capabilities
& Entry
->Attributes
) != Entry
->Attributes
) {
838 Status
= EFI_UNSUPPORTED
;
843 Link
= Link
->ForwardLink
;
847 // Allocate work space to perform this operation
849 Status
= CoreAllocateGcdMapEntry (&TopEntry
, &BottomEntry
);
850 if (EFI_ERROR (Status
)) {
851 Status
= EFI_OUT_OF_RESOURCES
;
854 ASSERT (TopEntry
!= NULL
&& BottomEntry
!= NULL
);
857 // Initialize CpuArchAttributes to suppress incorrect compiler/analyzer warnings.
859 CpuArchAttributes
= 0;
860 if (Operation
== GCD_SET_ATTRIBUTES_MEMORY_OPERATION
) {
862 // Call CPU Arch Protocol to attempt to set attributes on the range
864 CpuArchAttributes
= ConverToCpuArchAttributes (Attributes
);
866 // CPU arch attributes include page attributes and cache attributes.
867 // Only page attributes supports to be cleared, but not cache attributes.
868 // Caller is expected to use GetMemorySpaceDescriptor() to get the current
869 // attributes, AND/OR attributes, and then calls SetMemorySpaceAttributes()
870 // to set the new attributes.
871 // So 0 CPU arch attributes should not happen as memory should always have
872 // a cache attribute (no matter UC or WB, etc).
874 // Here, 0 CPU arch attributes will be filtered to be compatible with the
875 // case that caller just calls SetMemorySpaceAttributes() with none CPU
876 // arch attributes (for example, RUNTIME) as the purpose of the case is not
877 // to clear CPU arch attributes.
879 if (CpuArchAttributes
!= 0) {
881 Status
= EFI_NOT_AVAILABLE_YET
;
883 Status
= gCpu
->SetMemoryAttributes (
890 if (EFI_ERROR (Status
)) {
891 CoreFreePool (TopEntry
);
892 CoreFreePool (BottomEntry
);
899 // Convert/Insert the list of descriptors from StartLink to EndLink
902 while (Link
!= EndLink
->ForwardLink
) {
903 Entry
= CR (Link
, EFI_GCD_MAP_ENTRY
, Link
, EFI_GCD_MAP_SIGNATURE
);
904 CoreInsertGcdMapEntry (Link
, Entry
, BaseAddress
, Length
, TopEntry
, BottomEntry
);
909 case GCD_ADD_MEMORY_OPERATION
:
910 Entry
->GcdMemoryType
= GcdMemoryType
;
911 if (GcdMemoryType
== EfiGcdMemoryTypeMemoryMappedIo
) {
912 Entry
->Capabilities
= Capabilities
| EFI_MEMORY_RUNTIME
| EFI_MEMORY_PORT_IO
;
914 Entry
->Capabilities
= Capabilities
| EFI_MEMORY_RUNTIME
;
917 case GCD_ADD_IO_OPERATION
:
918 Entry
->GcdIoType
= GcdIoType
;
923 case GCD_FREE_MEMORY_OPERATION
:
924 case GCD_FREE_IO_OPERATION
:
925 Entry
->ImageHandle
= NULL
;
926 Entry
->DeviceHandle
= NULL
;
931 case GCD_REMOVE_MEMORY_OPERATION
:
932 Entry
->GcdMemoryType
= EfiGcdMemoryTypeNonExistent
;
933 Entry
->Capabilities
= 0;
935 case GCD_REMOVE_IO_OPERATION
:
936 Entry
->GcdIoType
= EfiGcdIoTypeNonExistent
;
939 // Set attributes operation
941 case GCD_SET_ATTRIBUTES_MEMORY_OPERATION
:
942 if (CpuArchAttributes
== 0) {
944 // Keep original CPU arch attributes when caller just calls
945 // SetMemorySpaceAttributes() with none CPU arch attributes (for example, RUNTIME).
947 Attributes
|= (Entry
->Attributes
& (EFI_CACHE_ATTRIBUTE_MASK
| EFI_MEMORY_ATTRIBUTE_MASK
));
949 Entry
->Attributes
= Attributes
;
952 // Set capabilities operation
954 case GCD_SET_CAPABILITIES_MEMORY_OPERATION
:
955 Entry
->Capabilities
= Capabilities
;
958 Link
= Link
->ForwardLink
;
964 Status
= CoreCleanupGcdMapEntry (TopEntry
, BottomEntry
, StartLink
, EndLink
, Map
);
967 DEBUG ((DEBUG_GCD
, " Status = %r\n", Status
));
969 if ((Operation
& GCD_MEMORY_SPACE_OPERATION
) != 0) {
970 CoreReleaseGcdMemoryLock ();
971 CoreDumpGcdMemorySpaceMap (FALSE
);
973 if ((Operation
& GCD_IO_SPACE_OPERATION
) != 0) {
974 CoreReleaseGcdIoLock ();
975 CoreDumpGcdIoSpaceMap (FALSE
);
983 Check whether an entry could be used to allocate space.
985 @param Operation Allocate memory or IO
986 @param Entry The entry to be tested
987 @param GcdMemoryType The desired memory type
988 @param GcdIoType The desired IO type
990 @retval EFI_NOT_FOUND The memory type does not match or there's an
991 image handle on the entry.
992 @retval EFI_UNSUPPORTED The operation unsupported.
993 @retval EFI_SUCCESS It's ok for this entry to be used to allocate
998 CoreAllocateSpaceCheckEntry (
1000 IN EFI_GCD_MAP_ENTRY
*Entry
,
1001 IN EFI_GCD_MEMORY_TYPE GcdMemoryType
,
1002 IN EFI_GCD_IO_TYPE GcdIoType
1005 if (Entry
->ImageHandle
!= NULL
) {
1006 return EFI_NOT_FOUND
;
1008 switch (Operation
) {
1009 case GCD_ALLOCATE_MEMORY_OPERATION
:
1010 if (Entry
->GcdMemoryType
!= GcdMemoryType
) {
1011 return EFI_NOT_FOUND
;
1014 case GCD_ALLOCATE_IO_OPERATION
:
1015 if (Entry
->GcdIoType
!= GcdIoType
) {
1016 return EFI_NOT_FOUND
;
1020 return EFI_UNSUPPORTED
;
1027 Allocate space on specified address and length.
1029 @param Operation The type of operation (memory or IO)
1030 @param GcdAllocateType The type of allocate operation
1031 @param GcdMemoryType The desired memory type
1032 @param GcdIoType The desired IO type
1033 @param Alignment Align with 2^Alignment
1034 @param Length Length to allocate
1035 @param BaseAddress Base address to allocate
1036 @param ImageHandle The image handle consume the allocated space.
1037 @param DeviceHandle The device handle consume the allocated space.
1039 @retval EFI_INVALID_PARAMETER Invalid parameter.
1040 @retval EFI_NOT_FOUND No descriptor for the desired space exists.
1041 @retval EFI_SUCCESS Space successfully allocated.
1047 IN EFI_GCD_ALLOCATE_TYPE GcdAllocateType
,
1048 IN EFI_GCD_MEMORY_TYPE GcdMemoryType
,
1049 IN EFI_GCD_IO_TYPE GcdIoType
,
1052 IN OUT EFI_PHYSICAL_ADDRESS
*BaseAddress
,
1053 IN EFI_HANDLE ImageHandle
,
1054 IN EFI_HANDLE DeviceHandle OPTIONAL
1058 EFI_PHYSICAL_ADDRESS AlignmentMask
;
1059 EFI_PHYSICAL_ADDRESS MaxAddress
;
1062 LIST_ENTRY
*SubLink
;
1063 EFI_GCD_MAP_ENTRY
*Entry
;
1064 EFI_GCD_MAP_ENTRY
*TopEntry
;
1065 EFI_GCD_MAP_ENTRY
*BottomEntry
;
1066 LIST_ENTRY
*StartLink
;
1067 LIST_ENTRY
*EndLink
;
1071 // Make sure parameters are valid
1073 if ((UINT32
)GcdAllocateType
>= EfiGcdMaxAllocateType
) {
1074 DEBUG ((DEBUG_GCD
, " Status = %r\n", EFI_INVALID_PARAMETER
));
1075 return EFI_INVALID_PARAMETER
;
1077 if ((UINT32
)GcdMemoryType
>= EfiGcdMemoryTypeMaximum
) {
1078 DEBUG ((DEBUG_GCD
, " Status = %r\n", EFI_INVALID_PARAMETER
));
1079 return EFI_INVALID_PARAMETER
;
1081 if ((UINT32
)GcdIoType
>= EfiGcdIoTypeMaximum
) {
1082 DEBUG ((DEBUG_GCD
, " Status = %r\n", EFI_INVALID_PARAMETER
));
1083 return EFI_INVALID_PARAMETER
;
1085 if (BaseAddress
== NULL
) {
1086 DEBUG ((DEBUG_GCD
, " Status = %r\n", EFI_INVALID_PARAMETER
));
1087 return EFI_INVALID_PARAMETER
;
1089 if (ImageHandle
== NULL
) {
1090 DEBUG ((DEBUG_GCD
, " Status = %r\n", EFI_INVALID_PARAMETER
));
1091 return EFI_INVALID_PARAMETER
;
1093 if (Alignment
>= 64) {
1094 DEBUG ((DEBUG_GCD
, " Status = %r\n", EFI_NOT_FOUND
));
1095 return EFI_NOT_FOUND
;
1098 DEBUG ((DEBUG_GCD
, " Status = %r\n", EFI_INVALID_PARAMETER
));
1099 return EFI_INVALID_PARAMETER
;
1103 if ((Operation
& GCD_MEMORY_SPACE_OPERATION
) != 0) {
1104 CoreAcquireGcdMemoryLock ();
1105 Map
= &mGcdMemorySpaceMap
;
1106 } else if ((Operation
& GCD_IO_SPACE_OPERATION
) != 0) {
1107 CoreAcquireGcdIoLock ();
1108 Map
= &mGcdIoSpaceMap
;
1117 // Compute alignment bit mask
1119 AlignmentMask
= LShiftU64 (1, Alignment
) - 1;
1121 if (GcdAllocateType
== EfiGcdAllocateAddress
) {
1123 // Verify that the BaseAddress passed in is aligned correctly
1125 if ((*BaseAddress
& AlignmentMask
) != 0) {
1126 Status
= EFI_NOT_FOUND
;
1131 // Search for the list of descriptors that cover the range BaseAddress to BaseAddress+Length
1133 Status
= CoreSearchGcdMapEntry (*BaseAddress
, Length
, &StartLink
, &EndLink
, Map
);
1134 if (EFI_ERROR (Status
)) {
1135 Status
= EFI_NOT_FOUND
;
1138 ASSERT (StartLink
!= NULL
&& EndLink
!= NULL
);
1141 // Verify that the list of descriptors are unallocated memory matching GcdMemoryType.
1144 while (Link
!= EndLink
->ForwardLink
) {
1145 Entry
= CR (Link
, EFI_GCD_MAP_ENTRY
, Link
, EFI_GCD_MAP_SIGNATURE
);
1146 Link
= Link
->ForwardLink
;
1147 Status
= CoreAllocateSpaceCheckEntry (Operation
, Entry
, GcdMemoryType
, GcdIoType
);
1148 if (EFI_ERROR (Status
)) {
1155 Entry
= CR (Map
->BackLink
, EFI_GCD_MAP_ENTRY
, Link
, EFI_GCD_MAP_SIGNATURE
);
1158 // Compute the maximum address to use in the search algorithm
1160 if (GcdAllocateType
== EfiGcdAllocateMaxAddressSearchBottomUp
||
1161 GcdAllocateType
== EfiGcdAllocateMaxAddressSearchTopDown
) {
1162 MaxAddress
= *BaseAddress
;
1164 MaxAddress
= Entry
->EndAddress
;
1168 // Verify that the list of descriptors are unallocated memory matching GcdMemoryType.
1170 if (GcdAllocateType
== EfiGcdAllocateMaxAddressSearchTopDown
||
1171 GcdAllocateType
== EfiGcdAllocateAnySearchTopDown
) {
1172 Link
= Map
->BackLink
;
1174 Link
= Map
->ForwardLink
;
1176 while (Link
!= Map
) {
1177 Entry
= CR (Link
, EFI_GCD_MAP_ENTRY
, Link
, EFI_GCD_MAP_SIGNATURE
);
1179 if (GcdAllocateType
== EfiGcdAllocateMaxAddressSearchTopDown
||
1180 GcdAllocateType
== EfiGcdAllocateAnySearchTopDown
) {
1181 Link
= Link
->BackLink
;
1183 Link
= Link
->ForwardLink
;
1186 Status
= CoreAllocateSpaceCheckEntry (Operation
, Entry
, GcdMemoryType
, GcdIoType
);
1187 if (EFI_ERROR (Status
)) {
1191 if (GcdAllocateType
== EfiGcdAllocateMaxAddressSearchTopDown
||
1192 GcdAllocateType
== EfiGcdAllocateAnySearchTopDown
) {
1193 if ((Entry
->BaseAddress
+ Length
) > MaxAddress
) {
1196 if (Length
> (Entry
->EndAddress
+ 1)) {
1197 Status
= EFI_NOT_FOUND
;
1200 if (Entry
->EndAddress
> MaxAddress
) {
1201 *BaseAddress
= MaxAddress
;
1203 *BaseAddress
= Entry
->EndAddress
;
1205 *BaseAddress
= (*BaseAddress
+ 1 - Length
) & (~AlignmentMask
);
1207 *BaseAddress
= (Entry
->BaseAddress
+ AlignmentMask
) & (~AlignmentMask
);
1208 if ((*BaseAddress
+ Length
- 1) > MaxAddress
) {
1209 Status
= EFI_NOT_FOUND
;
1215 // Search for the list of descriptors that cover the range BaseAddress to BaseAddress+Length
1217 Status
= CoreSearchGcdMapEntry (*BaseAddress
, Length
, &StartLink
, &EndLink
, Map
);
1218 if (EFI_ERROR (Status
)) {
1219 Status
= EFI_NOT_FOUND
;
1222 ASSERT (StartLink
!= NULL
&& EndLink
!= NULL
);
1226 // Verify that the list of descriptors are unallocated memory matching GcdMemoryType.
1229 SubLink
= StartLink
;
1230 while (SubLink
!= EndLink
->ForwardLink
) {
1231 Entry
= CR (SubLink
, EFI_GCD_MAP_ENTRY
, Link
, EFI_GCD_MAP_SIGNATURE
);
1232 Status
= CoreAllocateSpaceCheckEntry (Operation
, Entry
, GcdMemoryType
, GcdIoType
);
1233 if (EFI_ERROR (Status
)) {
1238 SubLink
= SubLink
->ForwardLink
;
1246 Status
= EFI_NOT_FOUND
;
1251 // Allocate work space to perform this operation
1253 Status
= CoreAllocateGcdMapEntry (&TopEntry
, &BottomEntry
);
1254 if (EFI_ERROR (Status
)) {
1255 Status
= EFI_OUT_OF_RESOURCES
;
1258 ASSERT (TopEntry
!= NULL
&& BottomEntry
!= NULL
);
1261 // Convert/Insert the list of descriptors from StartLink to EndLink
1264 while (Link
!= EndLink
->ForwardLink
) {
1265 Entry
= CR (Link
, EFI_GCD_MAP_ENTRY
, Link
, EFI_GCD_MAP_SIGNATURE
);
1266 CoreInsertGcdMapEntry (Link
, Entry
, *BaseAddress
, Length
, TopEntry
, BottomEntry
);
1267 Entry
->ImageHandle
= ImageHandle
;
1268 Entry
->DeviceHandle
= DeviceHandle
;
1269 Link
= Link
->ForwardLink
;
1275 Status
= CoreCleanupGcdMapEntry (TopEntry
, BottomEntry
, StartLink
, EndLink
, Map
);
1278 DEBUG ((DEBUG_GCD
, " Status = %r", Status
));
1279 if (!EFI_ERROR (Status
)) {
1280 DEBUG ((DEBUG_GCD
, " (BaseAddress = %016lx)", *BaseAddress
));
1282 DEBUG ((DEBUG_GCD
, "\n"));
1284 if ((Operation
& GCD_MEMORY_SPACE_OPERATION
) != 0) {
1285 CoreReleaseGcdMemoryLock ();
1286 CoreDumpGcdMemorySpaceMap (FALSE
);
1288 if ((Operation
& GCD_IO_SPACE_OPERATION
) !=0) {
1289 CoreReleaseGcdIoLock ();
1290 CoreDumpGcdIoSpaceMap (FALSE
);
1298 Add a segment of memory to GCD map.
1300 @param GcdMemoryType Memory type of the segment.
1301 @param BaseAddress Base address of the segment.
1302 @param Length Length of the segment.
1303 @param Capabilities alterable attributes of the segment.
1305 @retval EFI_INVALID_PARAMETER Invalid parameters.
1306 @retval EFI_SUCCESS Successfully add a segment of memory space.
1310 CoreInternalAddMemorySpace (
1311 IN EFI_GCD_MEMORY_TYPE GcdMemoryType
,
1312 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
1314 IN UINT64 Capabilities
1317 DEBUG ((DEBUG_GCD
, "GCD:AddMemorySpace(Base=%016lx,Length=%016lx)\n", BaseAddress
, Length
));
1318 DEBUG ((DEBUG_GCD
, " GcdMemoryType = %a\n", mGcdMemoryTypeNames
[MIN (GcdMemoryType
, EfiGcdMemoryTypeMaximum
)]));
1319 DEBUG ((DEBUG_GCD
, " Capabilities = %016lx\n", Capabilities
));
1322 // Make sure parameters are valid
1324 if (GcdMemoryType
<= EfiGcdMemoryTypeNonExistent
|| GcdMemoryType
>= EfiGcdMemoryTypeMaximum
) {
1325 return EFI_INVALID_PARAMETER
;
1328 return CoreConvertSpace (GCD_ADD_MEMORY_OPERATION
, GcdMemoryType
, (EFI_GCD_IO_TYPE
) 0, BaseAddress
, Length
, Capabilities
, 0);
1332 // GCD Core Services
1336 Allocates nonexistent memory, reserved memory, system memory, or memorymapped
1337 I/O resources from the global coherency domain of the processor.
1339 @param GcdAllocateType The type of allocate operation
1340 @param GcdMemoryType The desired memory type
1341 @param Alignment Align with 2^Alignment
1342 @param Length Length to allocate
1343 @param BaseAddress Base address to allocate
1344 @param ImageHandle The image handle consume the allocated space.
1345 @param DeviceHandle The device handle consume the allocated space.
1347 @retval EFI_INVALID_PARAMETER Invalid parameter.
1348 @retval EFI_NOT_FOUND No descriptor contains the desired space.
1349 @retval EFI_SUCCESS Memory space successfully allocated.
1354 CoreAllocateMemorySpace (
1355 IN EFI_GCD_ALLOCATE_TYPE GcdAllocateType
,
1356 IN EFI_GCD_MEMORY_TYPE GcdMemoryType
,
1359 IN OUT EFI_PHYSICAL_ADDRESS
*BaseAddress
,
1360 IN EFI_HANDLE ImageHandle
,
1361 IN EFI_HANDLE DeviceHandle OPTIONAL
1364 if (BaseAddress
!= NULL
) {
1365 DEBUG ((DEBUG_GCD
, "GCD:AllocateMemorySpace(Base=%016lx,Length=%016lx)\n", *BaseAddress
, Length
));
1367 DEBUG ((DEBUG_GCD
, "GCD:AllocateMemorySpace(Base=<NULL>,Length=%016lx)\n", Length
));
1369 DEBUG ((DEBUG_GCD
, " GcdAllocateType = %a\n", mGcdAllocationTypeNames
[MIN (GcdAllocateType
, EfiGcdMaxAllocateType
)]));
1370 DEBUG ((DEBUG_GCD
, " GcdMemoryType = %a\n", mGcdMemoryTypeNames
[MIN (GcdMemoryType
, EfiGcdMemoryTypeMaximum
)]));
1371 DEBUG ((DEBUG_GCD
, " Alignment = %016lx\n", LShiftU64 (1, Alignment
)));
1372 DEBUG ((DEBUG_GCD
, " ImageHandle = %p\n", ImageHandle
));
1373 DEBUG ((DEBUG_GCD
, " DeviceHandle = %p\n", DeviceHandle
));
1375 return CoreAllocateSpace (
1376 GCD_ALLOCATE_MEMORY_OPERATION
,
1379 (EFI_GCD_IO_TYPE
) 0,
1390 Adds reserved memory, system memory, or memory-mapped I/O resources to the
1391 global coherency domain of the processor.
1393 @param GcdMemoryType Memory type of the memory space.
1394 @param BaseAddress Base address of the memory space.
1395 @param Length Length of the memory space.
1396 @param Capabilities alterable attributes of the memory space.
1398 @retval EFI_SUCCESS Merged this memory space into GCD map.
1403 CoreAddMemorySpace (
1404 IN EFI_GCD_MEMORY_TYPE GcdMemoryType
,
1405 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
1407 IN UINT64 Capabilities
1411 EFI_PHYSICAL_ADDRESS PageBaseAddress
;
1414 Status
= CoreInternalAddMemorySpace (GcdMemoryType
, BaseAddress
, Length
, Capabilities
);
1416 if (!EFI_ERROR (Status
) && ((GcdMemoryType
== EfiGcdMemoryTypeSystemMemory
) || (GcdMemoryType
== EfiGcdMemoryTypeMoreReliable
))) {
1418 PageBaseAddress
= PageAlignAddress (BaseAddress
);
1419 PageLength
= PageAlignLength (BaseAddress
+ Length
- PageBaseAddress
);
1421 Status
= CoreAllocateMemorySpace (
1422 EfiGcdAllocateAddress
,
1427 gDxeCoreImageHandle
,
1431 if (!EFI_ERROR (Status
)) {
1432 CoreAddMemoryDescriptor (
1433 EfiConventionalMemory
,
1435 RShiftU64 (PageLength
, EFI_PAGE_SHIFT
),
1439 for (; PageLength
!= 0; PageLength
-= EFI_PAGE_SIZE
, PageBaseAddress
+= EFI_PAGE_SIZE
) {
1440 Status
= CoreAllocateMemorySpace (
1441 EfiGcdAllocateAddress
,
1446 gDxeCoreImageHandle
,
1450 if (!EFI_ERROR (Status
)) {
1451 CoreAddMemoryDescriptor (
1452 EfiConventionalMemory
,
1466 Frees nonexistent memory, reserved memory, system memory, or memory-mapped
1467 I/O resources from the global coherency domain of the processor.
1469 @param BaseAddress Base address of the memory space.
1470 @param Length Length of the memory space.
1472 @retval EFI_SUCCESS Space successfully freed.
1477 CoreFreeMemorySpace (
1478 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
1482 DEBUG ((DEBUG_GCD
, "GCD:FreeMemorySpace(Base=%016lx,Length=%016lx)\n", BaseAddress
, Length
));
1484 return CoreConvertSpace (GCD_FREE_MEMORY_OPERATION
, (EFI_GCD_MEMORY_TYPE
) 0, (EFI_GCD_IO_TYPE
) 0, BaseAddress
, Length
, 0, 0);
1489 Removes reserved memory, system memory, or memory-mapped I/O resources from
1490 the global coherency domain of the processor.
1492 @param BaseAddress Base address of the memory space.
1493 @param Length Length of the memory space.
1495 @retval EFI_SUCCESS Successfully remove a segment of memory space.
1500 CoreRemoveMemorySpace (
1501 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
1505 DEBUG ((DEBUG_GCD
, "GCD:RemoveMemorySpace(Base=%016lx,Length=%016lx)\n", BaseAddress
, Length
));
1507 return CoreConvertSpace (GCD_REMOVE_MEMORY_OPERATION
, (EFI_GCD_MEMORY_TYPE
) 0, (EFI_GCD_IO_TYPE
) 0, BaseAddress
, Length
, 0, 0);
1512 Build a memory descriptor according to an entry.
1514 @param Descriptor The descriptor to be built
1515 @param Entry According to this entry
1519 BuildMemoryDescriptor (
1520 IN OUT EFI_GCD_MEMORY_SPACE_DESCRIPTOR
*Descriptor
,
1521 IN EFI_GCD_MAP_ENTRY
*Entry
1524 Descriptor
->BaseAddress
= Entry
->BaseAddress
;
1525 Descriptor
->Length
= Entry
->EndAddress
- Entry
->BaseAddress
+ 1;
1526 Descriptor
->Capabilities
= Entry
->Capabilities
;
1527 Descriptor
->Attributes
= Entry
->Attributes
;
1528 Descriptor
->GcdMemoryType
= Entry
->GcdMemoryType
;
1529 Descriptor
->ImageHandle
= Entry
->ImageHandle
;
1530 Descriptor
->DeviceHandle
= Entry
->DeviceHandle
;
1535 Retrieves the descriptor for a memory region containing a specified address.
1537 @param BaseAddress Specified start address
1538 @param Descriptor Specified length
1540 @retval EFI_INVALID_PARAMETER Invalid parameter
1541 @retval EFI_SUCCESS Successfully get memory space descriptor.
1546 CoreGetMemorySpaceDescriptor (
1547 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
1548 OUT EFI_GCD_MEMORY_SPACE_DESCRIPTOR
*Descriptor
1552 LIST_ENTRY
*StartLink
;
1553 LIST_ENTRY
*EndLink
;
1554 EFI_GCD_MAP_ENTRY
*Entry
;
1557 // Make sure parameters are valid
1559 if (Descriptor
== NULL
) {
1560 return EFI_INVALID_PARAMETER
;
1563 CoreAcquireGcdMemoryLock ();
1566 // Search for the list of descriptors that contain BaseAddress
1568 Status
= CoreSearchGcdMapEntry (BaseAddress
, 1, &StartLink
, &EndLink
, &mGcdMemorySpaceMap
);
1569 if (EFI_ERROR (Status
)) {
1570 Status
= EFI_NOT_FOUND
;
1572 ASSERT (StartLink
!= NULL
&& EndLink
!= NULL
);
1574 // Copy the contents of the found descriptor into Descriptor
1576 Entry
= CR (StartLink
, EFI_GCD_MAP_ENTRY
, Link
, EFI_GCD_MAP_SIGNATURE
);
1577 BuildMemoryDescriptor (Descriptor
, Entry
);
1580 CoreReleaseGcdMemoryLock ();
1587 Modifies the attributes for a memory region in the global coherency domain of the
1590 @param BaseAddress Specified start address
1591 @param Length Specified length
1592 @param Attributes Specified attributes
1594 @retval EFI_SUCCESS The attributes were set for the memory region.
1595 @retval EFI_INVALID_PARAMETER Length is zero.
1596 @retval EFI_UNSUPPORTED The processor does not support one or more bytes of the memory
1597 resource range specified by BaseAddress and Length.
1598 @retval EFI_UNSUPPORTED The bit mask of attributes is not support for the memory resource
1599 range specified by BaseAddress and Length.
1600 @retval EFI_ACCESS_DEFINED The attributes for the memory resource range specified by
1601 BaseAddress and Length cannot be modified.
1602 @retval EFI_OUT_OF_RESOURCES There are not enough system resources to modify the attributes of
1603 the memory resource range.
1604 @retval EFI_NOT_AVAILABLE_YET The attributes cannot be set because CPU architectural protocol is
1610 CoreSetMemorySpaceAttributes (
1611 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
1613 IN UINT64 Attributes
1616 DEBUG ((DEBUG_GCD
, "GCD:SetMemorySpaceAttributes(Base=%016lx,Length=%016lx)\n", BaseAddress
, Length
));
1617 DEBUG ((DEBUG_GCD
, " Attributes = %016lx\n", Attributes
));
1619 return CoreConvertSpace (GCD_SET_ATTRIBUTES_MEMORY_OPERATION
, (EFI_GCD_MEMORY_TYPE
) 0, (EFI_GCD_IO_TYPE
) 0, BaseAddress
, Length
, 0, Attributes
);
1624 Modifies the capabilities for a memory region in the global coherency domain of the
1627 @param BaseAddress The physical address that is the start address of a memory region.
1628 @param Length The size in bytes of the memory region.
1629 @param Capabilities The bit mask of capabilities that the memory region supports.
1631 @retval EFI_SUCCESS The capabilities were set for the memory region.
1632 @retval EFI_INVALID_PARAMETER Length is zero.
1633 @retval EFI_UNSUPPORTED The capabilities specified by Capabilities do not include the
1634 memory region attributes currently in use.
1635 @retval EFI_ACCESS_DENIED The capabilities for the memory resource range specified by
1636 BaseAddress and Length cannot be modified.
1637 @retval EFI_OUT_OF_RESOURCES There are not enough system resources to modify the capabilities
1638 of the memory resource range.
1642 CoreSetMemorySpaceCapabilities (
1643 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
1645 IN UINT64 Capabilities
1650 DEBUG ((DEBUG_GCD
, "GCD:CoreSetMemorySpaceCapabilities(Base=%016lx,Length=%016lx)\n", BaseAddress
, Length
));
1651 DEBUG ((DEBUG_GCD
, " Capabilities = %016lx\n", Capabilities
));
1653 Status
= CoreConvertSpace (GCD_SET_CAPABILITIES_MEMORY_OPERATION
, (EFI_GCD_MEMORY_TYPE
) 0, (EFI_GCD_IO_TYPE
) 0, BaseAddress
, Length
, Capabilities
, 0);
1654 if (!EFI_ERROR(Status
)) {
1655 CoreUpdateMemoryAttributes(BaseAddress
, RShiftU64(Length
, EFI_PAGE_SHIFT
), Capabilities
& (~EFI_MEMORY_RUNTIME
));
1663 Returns a map of the memory resources in the global coherency domain of the
1666 @param NumberOfDescriptors Number of descriptors.
1667 @param MemorySpaceMap Descriptor array
1669 @retval EFI_INVALID_PARAMETER Invalid parameter
1670 @retval EFI_OUT_OF_RESOURCES No enough buffer to allocate
1671 @retval EFI_SUCCESS Successfully get memory space map.
1676 CoreGetMemorySpaceMap (
1677 OUT UINTN
*NumberOfDescriptors
,
1678 OUT EFI_GCD_MEMORY_SPACE_DESCRIPTOR
**MemorySpaceMap
1682 EFI_GCD_MAP_ENTRY
*Entry
;
1683 EFI_GCD_MEMORY_SPACE_DESCRIPTOR
*Descriptor
;
1684 UINTN DescriptorCount
;
1687 // Make sure parameters are valid
1689 if (NumberOfDescriptors
== NULL
) {
1690 return EFI_INVALID_PARAMETER
;
1692 if (MemorySpaceMap
== NULL
) {
1693 return EFI_INVALID_PARAMETER
;
1696 *NumberOfDescriptors
= 0;
1697 *MemorySpaceMap
= NULL
;
1700 // Take the lock, for entering the loop with the lock held.
1702 CoreAcquireGcdMemoryLock ();
1705 // Count descriptors. It might be done more than once because the
1706 // AllocatePool() called below has to be running outside the GCD lock.
1708 DescriptorCount
= CoreCountGcdMapEntry (&mGcdMemorySpaceMap
);
1709 if (DescriptorCount
== *NumberOfDescriptors
&& *MemorySpaceMap
!= NULL
) {
1711 // Fill in the MemorySpaceMap if no memory space map change.
1713 Descriptor
= *MemorySpaceMap
;
1714 Link
= mGcdMemorySpaceMap
.ForwardLink
;
1715 while (Link
!= &mGcdMemorySpaceMap
) {
1716 Entry
= CR (Link
, EFI_GCD_MAP_ENTRY
, Link
, EFI_GCD_MAP_SIGNATURE
);
1717 BuildMemoryDescriptor (Descriptor
, Entry
);
1719 Link
= Link
->ForwardLink
;
1722 // We're done; exit the loop with the lock held.
1728 // Release the lock before memory allocation, because it might cause
1729 // GCD lock conflict in one of calling path in AllocatPool().
1731 CoreReleaseGcdMemoryLock ();
1734 // Allocate memory to store the MemorySpaceMap. Note it might be already
1735 // allocated if there's map descriptor change during memory allocation at
1738 if (*MemorySpaceMap
!= NULL
) {
1739 FreePool (*MemorySpaceMap
);
1742 *MemorySpaceMap
= AllocatePool (DescriptorCount
*
1743 sizeof (EFI_GCD_MEMORY_SPACE_DESCRIPTOR
));
1744 if (*MemorySpaceMap
== NULL
) {
1745 *NumberOfDescriptors
= 0;
1746 return EFI_OUT_OF_RESOURCES
;
1750 // Save the descriptor count got before for another round of check to make
1751 // sure we won't miss any, since we have code running outside the GCD lock.
1753 *NumberOfDescriptors
= DescriptorCount
;
1755 // Re-acquire the lock, for the next iteration.
1757 CoreAcquireGcdMemoryLock ();
1760 // We exited the loop with the lock held, release it.
1762 CoreReleaseGcdMemoryLock ();
1769 Adds reserved I/O or I/O resources to the global coherency domain of the processor.
1771 @param GcdIoType IO type of the segment.
1772 @param BaseAddress Base address of the segment.
1773 @param Length Length of the segment.
1775 @retval EFI_SUCCESS Merged this segment into GCD map.
1776 @retval EFI_INVALID_PARAMETER Parameter not valid
1782 IN EFI_GCD_IO_TYPE GcdIoType
,
1783 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
1787 DEBUG ((DEBUG_GCD
, "GCD:AddIoSpace(Base=%016lx,Length=%016lx)\n", BaseAddress
, Length
));
1788 DEBUG ((DEBUG_GCD
, " GcdIoType = %a\n", mGcdIoTypeNames
[MIN (GcdIoType
, EfiGcdIoTypeMaximum
)]));
1791 // Make sure parameters are valid
1793 if (GcdIoType
<= EfiGcdIoTypeNonExistent
|| GcdIoType
>= EfiGcdIoTypeMaximum
) {
1794 return EFI_INVALID_PARAMETER
;
1796 return CoreConvertSpace (GCD_ADD_IO_OPERATION
, (EFI_GCD_MEMORY_TYPE
) 0, GcdIoType
, BaseAddress
, Length
, 0, 0);
1801 Allocates nonexistent I/O, reserved I/O, or I/O resources from the global coherency
1802 domain of the processor.
1804 @param GcdAllocateType The type of allocate operation
1805 @param GcdIoType The desired IO type
1806 @param Alignment Align with 2^Alignment
1807 @param Length Length to allocate
1808 @param BaseAddress Base address to allocate
1809 @param ImageHandle The image handle consume the allocated space.
1810 @param DeviceHandle The device handle consume the allocated space.
1812 @retval EFI_INVALID_PARAMETER Invalid parameter.
1813 @retval EFI_NOT_FOUND No descriptor contains the desired space.
1814 @retval EFI_SUCCESS IO space successfully allocated.
1819 CoreAllocateIoSpace (
1820 IN EFI_GCD_ALLOCATE_TYPE GcdAllocateType
,
1821 IN EFI_GCD_IO_TYPE GcdIoType
,
1824 IN OUT EFI_PHYSICAL_ADDRESS
*BaseAddress
,
1825 IN EFI_HANDLE ImageHandle
,
1826 IN EFI_HANDLE DeviceHandle OPTIONAL
1829 if (BaseAddress
!= NULL
) {
1830 DEBUG ((DEBUG_GCD
, "GCD:AllocateIoSpace(Base=%016lx,Length=%016lx)\n", *BaseAddress
, Length
));
1832 DEBUG ((DEBUG_GCD
, "GCD:AllocateIoSpace(Base=<NULL>,Length=%016lx)\n", Length
));
1834 DEBUG ((DEBUG_GCD
, " GcdAllocateType = %a\n", mGcdAllocationTypeNames
[MIN (GcdAllocateType
, EfiGcdMaxAllocateType
)]));
1835 DEBUG ((DEBUG_GCD
, " GcdIoType = %a\n", mGcdIoTypeNames
[MIN (GcdIoType
, EfiGcdIoTypeMaximum
)]));
1836 DEBUG ((DEBUG_GCD
, " Alignment = %016lx\n", LShiftU64 (1, Alignment
)));
1837 DEBUG ((DEBUG_GCD
, " ImageHandle = %p\n", ImageHandle
));
1838 DEBUG ((DEBUG_GCD
, " DeviceHandle = %p\n", DeviceHandle
));
1840 return CoreAllocateSpace (
1841 GCD_ALLOCATE_IO_OPERATION
,
1843 (EFI_GCD_MEMORY_TYPE
) 0,
1855 Frees nonexistent I/O, reserved I/O, or I/O resources from the global coherency
1856 domain of the processor.
1858 @param BaseAddress Base address of the segment.
1859 @param Length Length of the segment.
1861 @retval EFI_SUCCESS Space successfully freed.
1867 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
1871 DEBUG ((DEBUG_GCD
, "GCD:FreeIoSpace(Base=%016lx,Length=%016lx)\n", BaseAddress
, Length
));
1873 return CoreConvertSpace (GCD_FREE_IO_OPERATION
, (EFI_GCD_MEMORY_TYPE
) 0, (EFI_GCD_IO_TYPE
) 0, BaseAddress
, Length
, 0, 0);
1878 Removes reserved I/O or I/O resources from the global coherency domain of the
1881 @param BaseAddress Base address of the segment.
1882 @param Length Length of the segment.
1884 @retval EFI_SUCCESS Successfully removed a segment of IO space.
1890 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
1894 DEBUG ((DEBUG_GCD
, "GCD:RemoveIoSpace(Base=%016lx,Length=%016lx)\n", BaseAddress
, Length
));
1896 return CoreConvertSpace (GCD_REMOVE_IO_OPERATION
, (EFI_GCD_MEMORY_TYPE
) 0, (EFI_GCD_IO_TYPE
) 0, BaseAddress
, Length
, 0, 0);
1901 Build a IO descriptor according to an entry.
1903 @param Descriptor The descriptor to be built
1904 @param Entry According to this entry
1909 IN EFI_GCD_IO_SPACE_DESCRIPTOR
*Descriptor
,
1910 IN EFI_GCD_MAP_ENTRY
*Entry
1913 Descriptor
->BaseAddress
= Entry
->BaseAddress
;
1914 Descriptor
->Length
= Entry
->EndAddress
- Entry
->BaseAddress
+ 1;
1915 Descriptor
->GcdIoType
= Entry
->GcdIoType
;
1916 Descriptor
->ImageHandle
= Entry
->ImageHandle
;
1917 Descriptor
->DeviceHandle
= Entry
->DeviceHandle
;
1922 Retrieves the descriptor for an I/O region containing a specified address.
1924 @param BaseAddress Specified start address
1925 @param Descriptor Specified length
1927 @retval EFI_INVALID_PARAMETER Descriptor is NULL.
1928 @retval EFI_SUCCESS Successfully get the IO space descriptor.
1933 CoreGetIoSpaceDescriptor (
1934 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
1935 OUT EFI_GCD_IO_SPACE_DESCRIPTOR
*Descriptor
1939 LIST_ENTRY
*StartLink
;
1940 LIST_ENTRY
*EndLink
;
1941 EFI_GCD_MAP_ENTRY
*Entry
;
1944 // Make sure parameters are valid
1946 if (Descriptor
== NULL
) {
1947 return EFI_INVALID_PARAMETER
;
1950 CoreAcquireGcdIoLock ();
1953 // Search for the list of descriptors that contain BaseAddress
1955 Status
= CoreSearchGcdMapEntry (BaseAddress
, 1, &StartLink
, &EndLink
, &mGcdIoSpaceMap
);
1956 if (EFI_ERROR (Status
)) {
1957 Status
= EFI_NOT_FOUND
;
1959 ASSERT (StartLink
!= NULL
&& EndLink
!= NULL
);
1961 // Copy the contents of the found descriptor into Descriptor
1963 Entry
= CR (StartLink
, EFI_GCD_MAP_ENTRY
, Link
, EFI_GCD_MAP_SIGNATURE
);
1964 BuildIoDescriptor (Descriptor
, Entry
);
1967 CoreReleaseGcdIoLock ();
1974 Returns a map of the I/O resources in the global coherency domain of the processor.
1976 @param NumberOfDescriptors Number of descriptors.
1977 @param IoSpaceMap Descriptor array
1979 @retval EFI_INVALID_PARAMETER Invalid parameter
1980 @retval EFI_OUT_OF_RESOURCES No enough buffer to allocate
1981 @retval EFI_SUCCESS Successfully get IO space map.
1987 OUT UINTN
*NumberOfDescriptors
,
1988 OUT EFI_GCD_IO_SPACE_DESCRIPTOR
**IoSpaceMap
1993 EFI_GCD_MAP_ENTRY
*Entry
;
1994 EFI_GCD_IO_SPACE_DESCRIPTOR
*Descriptor
;
1997 // Make sure parameters are valid
1999 if (NumberOfDescriptors
== NULL
) {
2000 return EFI_INVALID_PARAMETER
;
2002 if (IoSpaceMap
== NULL
) {
2003 return EFI_INVALID_PARAMETER
;
2006 CoreAcquireGcdIoLock ();
2009 // Count the number of descriptors
2011 *NumberOfDescriptors
= CoreCountGcdMapEntry (&mGcdIoSpaceMap
);
2014 // Allocate the IoSpaceMap
2016 *IoSpaceMap
= AllocatePool (*NumberOfDescriptors
* sizeof (EFI_GCD_IO_SPACE_DESCRIPTOR
));
2017 if (*IoSpaceMap
== NULL
) {
2018 Status
= EFI_OUT_OF_RESOURCES
;
2023 // Fill in the IoSpaceMap
2025 Descriptor
= *IoSpaceMap
;
2026 Link
= mGcdIoSpaceMap
.ForwardLink
;
2027 while (Link
!= &mGcdIoSpaceMap
) {
2028 Entry
= CR (Link
, EFI_GCD_MAP_ENTRY
, Link
, EFI_GCD_MAP_SIGNATURE
);
2029 BuildIoDescriptor (Descriptor
, Entry
);
2031 Link
= Link
->ForwardLink
;
2033 Status
= EFI_SUCCESS
;
2036 CoreReleaseGcdIoLock ();
2042 Converts a Resource Descriptor HOB attributes mask to an EFI Memory Descriptor
2045 @param GcdMemoryType Type of resource in the GCD memory map.
2046 @param Attributes The attribute mask in the Resource Descriptor
2049 @return The capabilities mask for an EFI Memory Descriptor.
2053 CoreConvertResourceDescriptorHobAttributesToCapabilities (
2054 EFI_GCD_MEMORY_TYPE GcdMemoryType
,
2058 UINT64 Capabilities
;
2059 GCD_ATTRIBUTE_CONVERSION_ENTRY
*Conversion
;
2062 // Convert the Resource HOB Attributes to an EFI Memory Capabilities mask
2064 for (Capabilities
= 0, Conversion
= mAttributeConversionTable
; Conversion
->Attribute
!= 0; Conversion
++) {
2065 if (Conversion
->Memory
|| ((GcdMemoryType
!= EfiGcdMemoryTypeSystemMemory
) && (GcdMemoryType
!= EfiGcdMemoryTypeMoreReliable
))) {
2066 if (Attributes
& Conversion
->Attribute
) {
2067 Capabilities
|= Conversion
->Capability
;
2072 return Capabilities
;
2076 Calculate total memory bin size neeeded.
2078 @return The total memory bin size neeeded.
2082 CalculateTotalMemoryBinSizeNeeded (
2090 // Loop through each memory type in the order specified by the gMemoryTypeInformation[] array
2093 for (Index
= 0; gMemoryTypeInformation
[Index
].Type
!= EfiMaxMemoryType
; Index
++) {
2094 TotalSize
+= LShiftU64 (gMemoryTypeInformation
[Index
].NumberOfPages
, EFI_PAGE_SHIFT
);
2101 Find the largest region in the specified region that is not covered by an existing memory allocation
2103 @param BaseAddress On input start of the region to check.
2104 On output start of the largest free region.
2105 @param Length On input size of region to check.
2106 On output size of the largest free region.
2107 @param MemoryHob Hob pointer for the first memory allocation pointer to check
2110 FindLargestFreeRegion (
2111 IN OUT EFI_PHYSICAL_ADDRESS
*BaseAddress
,
2112 IN OUT UINT64
*Length
,
2113 IN EFI_HOB_MEMORY_ALLOCATION
*MemoryHob
2116 EFI_PHYSICAL_ADDRESS TopAddress
;
2117 EFI_PHYSICAL_ADDRESS AllocatedTop
;
2118 EFI_PHYSICAL_ADDRESS LowerBase
;
2120 EFI_PHYSICAL_ADDRESS UpperBase
;
2123 TopAddress
= *BaseAddress
+ *Length
;
2124 while (MemoryHob
!= NULL
) {
2125 AllocatedTop
= MemoryHob
->AllocDescriptor
.MemoryBaseAddress
+ MemoryHob
->AllocDescriptor
.MemoryLength
;
2127 if ((MemoryHob
->AllocDescriptor
.MemoryBaseAddress
>= *BaseAddress
) &&
2128 (AllocatedTop
<= TopAddress
)) {
2129 LowerBase
= *BaseAddress
;
2130 LowerSize
= MemoryHob
->AllocDescriptor
.MemoryBaseAddress
- *BaseAddress
;
2131 UpperBase
= AllocatedTop
;
2132 UpperSize
= TopAddress
- AllocatedTop
;
2134 if (LowerSize
!= 0) {
2135 FindLargestFreeRegion (&LowerBase
, &LowerSize
, (EFI_HOB_MEMORY_ALLOCATION
*) GetNextHob (EFI_HOB_TYPE_MEMORY_ALLOCATION
, GET_NEXT_HOB (MemoryHob
)));
2137 if (UpperSize
!= 0) {
2138 FindLargestFreeRegion (&UpperBase
, &UpperSize
, (EFI_HOB_MEMORY_ALLOCATION
*) GetNextHob (EFI_HOB_TYPE_MEMORY_ALLOCATION
, GET_NEXT_HOB (MemoryHob
)));
2141 if (UpperSize
>= LowerSize
) {
2142 *Length
= UpperSize
;
2143 *BaseAddress
= UpperBase
;
2145 *Length
= LowerSize
;
2146 *BaseAddress
= LowerBase
;
2150 MemoryHob
= GetNextHob (EFI_HOB_TYPE_MEMORY_ALLOCATION
, GET_NEXT_HOB (MemoryHob
));
2155 External function. Initializes memory services based on the memory
2156 descriptor HOBs. This function is responsible for priming the memory
2157 map, so memory allocations and resource allocations can be made.
2158 The first part of this function can not depend on any memory services
2159 until at least one memory descriptor is provided to the memory services.
2161 @param HobStart The start address of the HOB.
2162 @param MemoryBaseAddress Start address of memory region found to init DXE
2164 @param MemoryLength Length of memory region found to init DXE core.
2166 @retval EFI_SUCCESS Memory services successfully initialized.
2170 CoreInitializeMemoryServices (
2172 OUT EFI_PHYSICAL_ADDRESS
*MemoryBaseAddress
,
2173 OUT UINT64
*MemoryLength
2176 EFI_PEI_HOB_POINTERS Hob
;
2177 EFI_MEMORY_TYPE_INFORMATION
*EfiMemoryTypeInformation
;
2180 EFI_HOB_HANDOFF_INFO_TABLE
*PhitHob
;
2181 EFI_HOB_RESOURCE_DESCRIPTOR
*ResourceHob
;
2182 EFI_HOB_RESOURCE_DESCRIPTOR
*PhitResourceHob
;
2183 EFI_PHYSICAL_ADDRESS BaseAddress
;
2186 UINT64 Capabilities
;
2187 EFI_PHYSICAL_ADDRESS TestedMemoryBaseAddress
;
2188 UINT64 TestedMemoryLength
;
2189 EFI_PHYSICAL_ADDRESS HighAddress
;
2190 EFI_HOB_GUID_TYPE
*GuidHob
;
2191 UINT32 ReservedCodePageNumber
;
2192 UINT64 MinimalMemorySizeNeeded
;
2195 // Point at the first HOB. This must be the PHIT HOB.
2197 Hob
.Raw
= *HobStart
;
2198 ASSERT (GET_HOB_TYPE (Hob
) == EFI_HOB_TYPE_HANDOFF
);
2201 // Initialize the spin locks and maps in the memory services.
2202 // Also fill in the memory services into the EFI Boot Services Table
2204 CoreInitializePool ();
2207 // Initialize Local Variables
2209 PhitResourceHob
= NULL
;
2216 // Cache the PHIT HOB for later use
2218 PhitHob
= Hob
.HandoffInformationTable
;
2220 if (PcdGet64(PcdLoadModuleAtFixAddressEnable
) != 0) {
2221 ReservedCodePageNumber
= PcdGet32(PcdLoadFixAddressRuntimeCodePageNumber
);
2222 ReservedCodePageNumber
+= PcdGet32(PcdLoadFixAddressBootTimeCodePageNumber
);
2225 // cache the Top address for loading modules at Fixed Address
2227 gLoadModuleAtFixAddressConfigurationTable
.DxeCodeTopAddress
= PhitHob
->EfiMemoryTop
2228 + EFI_PAGES_TO_SIZE(ReservedCodePageNumber
);
2231 // See if a Memory Type Information HOB is available
2233 GuidHob
= GetFirstGuidHob (&gEfiMemoryTypeInformationGuid
);
2234 if (GuidHob
!= NULL
) {
2235 EfiMemoryTypeInformation
= GET_GUID_HOB_DATA (GuidHob
);
2236 DataSize
= GET_GUID_HOB_DATA_SIZE (GuidHob
);
2237 if (EfiMemoryTypeInformation
!= NULL
&& DataSize
> 0 && DataSize
<= (EfiMaxMemoryType
+ 1) * sizeof (EFI_MEMORY_TYPE_INFORMATION
)) {
2238 CopyMem (&gMemoryTypeInformation
, EfiMemoryTypeInformation
, DataSize
);
2243 // Include the total memory bin size needed to make sure memory bin could be allocated successfully.
2245 MinimalMemorySizeNeeded
= MINIMUM_INITIAL_MEMORY_SIZE
+ CalculateTotalMemoryBinSizeNeeded ();
2248 // Find the Resource Descriptor HOB that contains PHIT range EfiFreeMemoryBottom..EfiFreeMemoryTop
2251 for (Hob
.Raw
= *HobStart
; !END_OF_HOB_LIST(Hob
); Hob
.Raw
= GET_NEXT_HOB(Hob
)) {
2253 // Skip all HOBs except Resource Descriptor HOBs
2255 if (GET_HOB_TYPE (Hob
) != EFI_HOB_TYPE_RESOURCE_DESCRIPTOR
) {
2260 // Skip Resource Descriptor HOBs that do not describe tested system memory
2262 ResourceHob
= Hob
.ResourceDescriptor
;
2263 if (ResourceHob
->ResourceType
!= EFI_RESOURCE_SYSTEM_MEMORY
) {
2266 if ((ResourceHob
->ResourceAttribute
& MEMORY_ATTRIBUTE_MASK
) != TESTED_MEMORY_ATTRIBUTES
) {
2271 // Skip Resource Descriptor HOBs that do not contain the PHIT range EfiFreeMemoryBottom..EfiFreeMemoryTop
2273 if (PhitHob
->EfiFreeMemoryBottom
< ResourceHob
->PhysicalStart
) {
2276 if (PhitHob
->EfiFreeMemoryTop
> (ResourceHob
->PhysicalStart
+ ResourceHob
->ResourceLength
)) {
2281 // Cache the resource descriptor HOB for the memory region described by the PHIT HOB
2283 PhitResourceHob
= ResourceHob
;
2287 // Compute range between PHIT EfiMemoryTop and the end of the Resource Descriptor HOB
2289 Attributes
= PhitResourceHob
->ResourceAttribute
;
2290 BaseAddress
= PageAlignAddress (PhitHob
->EfiMemoryTop
);
2291 Length
= PageAlignLength (ResourceHob
->PhysicalStart
+ ResourceHob
->ResourceLength
- BaseAddress
);
2292 FindLargestFreeRegion (&BaseAddress
, &Length
, (EFI_HOB_MEMORY_ALLOCATION
*)GetFirstHob (EFI_HOB_TYPE_MEMORY_ALLOCATION
));
2293 if (Length
< MinimalMemorySizeNeeded
) {
2295 // If that range is not large enough to intialize the DXE Core, then
2296 // Compute range between PHIT EfiFreeMemoryBottom and PHIT EfiFreeMemoryTop
2298 BaseAddress
= PageAlignAddress (PhitHob
->EfiFreeMemoryBottom
);
2299 Length
= PageAlignLength (PhitHob
->EfiFreeMemoryTop
- BaseAddress
);
2300 //This region is required to have no memory allocation inside it, skip check for entries in HOB List
2301 if (Length
< MinimalMemorySizeNeeded
) {
2303 // If that range is not large enough to intialize the DXE Core, then
2304 // Compute range between the start of the Resource Descriptor HOB and the start of the HOB List
2306 BaseAddress
= PageAlignAddress (ResourceHob
->PhysicalStart
);
2307 Length
= PageAlignLength ((UINT64
)((UINTN
)*HobStart
- BaseAddress
));
2308 FindLargestFreeRegion (&BaseAddress
, &Length
, (EFI_HOB_MEMORY_ALLOCATION
*)GetFirstHob (EFI_HOB_TYPE_MEMORY_ALLOCATION
));
2315 // Assert if a resource descriptor HOB for the memory region described by the PHIT was not found
2320 // Take the range in the resource descriptor HOB for the memory region described
2321 // by the PHIT as higher priority if it is big enough. It can make the memory bin
2322 // allocated to be at the same memory region with PHIT that has more better compatibility
2323 // to avoid memory fragmentation for some code practices assume and allocate <4G ACPI memory.
2325 if (Length
< MinimalMemorySizeNeeded
) {
2327 // Search all the resource descriptor HOBs from the highest possible addresses down for a memory
2328 // region that is big enough to initialize the DXE core. Always skip the PHIT Resource HOB.
2329 // The max address must be within the physically addressible range for the processor.
2331 HighAddress
= MAX_ALLOC_ADDRESS
;
2332 for (Hob
.Raw
= *HobStart
; !END_OF_HOB_LIST(Hob
); Hob
.Raw
= GET_NEXT_HOB(Hob
)) {
2334 // Skip the Resource Descriptor HOB that contains the PHIT
2336 if (Hob
.ResourceDescriptor
== PhitResourceHob
) {
2340 // Skip all HOBs except Resource Descriptor HOBs
2342 if (GET_HOB_TYPE (Hob
) != EFI_HOB_TYPE_RESOURCE_DESCRIPTOR
) {
2347 // Skip Resource Descriptor HOBs that do not describe tested system memory below MAX_ALLOC_ADDRESS
2349 ResourceHob
= Hob
.ResourceDescriptor
;
2350 if (ResourceHob
->ResourceType
!= EFI_RESOURCE_SYSTEM_MEMORY
) {
2353 if ((ResourceHob
->ResourceAttribute
& MEMORY_ATTRIBUTE_MASK
) != TESTED_MEMORY_ATTRIBUTES
) {
2356 if ((ResourceHob
->PhysicalStart
+ ResourceHob
->ResourceLength
) > (EFI_PHYSICAL_ADDRESS
)MAX_ALLOC_ADDRESS
) {
2361 // Skip Resource Descriptor HOBs that are below a previously found Resource Descriptor HOB
2363 if (HighAddress
!= (EFI_PHYSICAL_ADDRESS
)MAX_ALLOC_ADDRESS
&& ResourceHob
->PhysicalStart
<= HighAddress
) {
2368 // Skip Resource Descriptor HOBs that are not large enough to initilize the DXE Core
2370 TestedMemoryBaseAddress
= PageAlignAddress (ResourceHob
->PhysicalStart
);
2371 TestedMemoryLength
= PageAlignLength (ResourceHob
->PhysicalStart
+ ResourceHob
->ResourceLength
- TestedMemoryBaseAddress
);
2372 FindLargestFreeRegion (&TestedMemoryBaseAddress
, &TestedMemoryLength
, (EFI_HOB_MEMORY_ALLOCATION
*)GetFirstHob (EFI_HOB_TYPE_MEMORY_ALLOCATION
));
2373 if (TestedMemoryLength
< MinimalMemorySizeNeeded
) {
2378 // Save the range described by the Resource Descriptor that is large enough to initilize the DXE Core
2380 BaseAddress
= TestedMemoryBaseAddress
;
2381 Length
= TestedMemoryLength
;
2382 Attributes
= ResourceHob
->ResourceAttribute
;
2383 HighAddress
= ResourceHob
->PhysicalStart
;
2387 DEBUG ((EFI_D_INFO
, "CoreInitializeMemoryServices:\n"));
2388 DEBUG ((EFI_D_INFO
, " BaseAddress - 0x%lx Length - 0x%lx MinimalMemorySizeNeeded - 0x%lx\n", BaseAddress
, Length
, MinimalMemorySizeNeeded
));
2391 // If no memory regions are found that are big enough to initialize the DXE core, then ASSERT().
2393 ASSERT (Length
>= MinimalMemorySizeNeeded
);
2396 // Convert the Resource HOB Attributes to an EFI Memory Capabilities mask
2398 if ((Attributes
& EFI_RESOURCE_ATTRIBUTE_MORE_RELIABLE
) == EFI_RESOURCE_ATTRIBUTE_MORE_RELIABLE
) {
2399 Capabilities
= CoreConvertResourceDescriptorHobAttributesToCapabilities (EfiGcdMemoryTypeMoreReliable
, Attributes
);
2401 Capabilities
= CoreConvertResourceDescriptorHobAttributesToCapabilities (EfiGcdMemoryTypeSystemMemory
, Attributes
);
2405 // Declare the very first memory region, so the EFI Memory Services are available.
2407 CoreAddMemoryDescriptor (
2408 EfiConventionalMemory
,
2410 RShiftU64 (Length
, EFI_PAGE_SHIFT
),
2414 *MemoryBaseAddress
= BaseAddress
;
2415 *MemoryLength
= Length
;
2422 External function. Initializes the GCD and memory services based on the memory
2423 descriptor HOBs. This function is responsible for priming the GCD map and the
2424 memory map, so memory allocations and resource allocations can be made. The
2425 HobStart will be relocated to a pool buffer.
2427 @param HobStart The start address of the HOB
2428 @param MemoryBaseAddress Start address of memory region found to init DXE
2430 @param MemoryLength Length of memory region found to init DXE core.
2432 @retval EFI_SUCCESS GCD services successfully initialized.
2436 CoreInitializeGcdServices (
2437 IN OUT VOID
**HobStart
,
2438 IN EFI_PHYSICAL_ADDRESS MemoryBaseAddress
,
2439 IN UINT64 MemoryLength
2442 EFI_PEI_HOB_POINTERS Hob
;
2444 EFI_HOB_HANDOFF_INFO_TABLE
*PhitHob
;
2445 UINT8 SizeOfMemorySpace
;
2446 UINT8 SizeOfIoSpace
;
2447 EFI_HOB_RESOURCE_DESCRIPTOR
*ResourceHob
;
2448 EFI_PHYSICAL_ADDRESS BaseAddress
;
2451 EFI_GCD_MAP_ENTRY
*Entry
;
2452 EFI_GCD_MEMORY_TYPE GcdMemoryType
;
2453 EFI_GCD_IO_TYPE GcdIoType
;
2454 EFI_GCD_MEMORY_SPACE_DESCRIPTOR Descriptor
;
2455 EFI_HOB_MEMORY_ALLOCATION
*MemoryHob
;
2456 EFI_HOB_FIRMWARE_VOLUME
*FirmwareVolumeHob
;
2457 UINTN NumberOfDescriptors
;
2458 EFI_GCD_MEMORY_SPACE_DESCRIPTOR
*MemorySpaceMap
;
2460 UINT64 Capabilities
;
2461 EFI_HOB_CPU
* CpuHob
;
2462 EFI_GCD_MEMORY_SPACE_DESCRIPTOR
*MemorySpaceMapHobList
;
2465 // Cache the PHIT HOB for later use
2467 PhitHob
= (EFI_HOB_HANDOFF_INFO_TABLE
*)(*HobStart
);
2470 // Get the number of address lines in the I/O and Memory space for the CPU
2472 CpuHob
= GetFirstHob (EFI_HOB_TYPE_CPU
);
2473 ASSERT (CpuHob
!= NULL
);
2474 SizeOfMemorySpace
= CpuHob
->SizeOfMemorySpace
;
2475 SizeOfIoSpace
= CpuHob
->SizeOfIoSpace
;
2478 // Initialize the GCD Memory Space Map
2480 Entry
= AllocateCopyPool (sizeof (EFI_GCD_MAP_ENTRY
), &mGcdMemorySpaceMapEntryTemplate
);
2481 ASSERT (Entry
!= NULL
);
2483 Entry
->EndAddress
= LShiftU64 (1, SizeOfMemorySpace
) - 1;
2485 InsertHeadList (&mGcdMemorySpaceMap
, &Entry
->Link
);
2487 CoreDumpGcdMemorySpaceMap (TRUE
);
2490 // Initialize the GCD I/O Space Map
2492 Entry
= AllocateCopyPool (sizeof (EFI_GCD_MAP_ENTRY
), &mGcdIoSpaceMapEntryTemplate
);
2493 ASSERT (Entry
!= NULL
);
2495 Entry
->EndAddress
= LShiftU64 (1, SizeOfIoSpace
) - 1;
2497 InsertHeadList (&mGcdIoSpaceMap
, &Entry
->Link
);
2499 CoreDumpGcdIoSpaceMap (TRUE
);
2502 // Walk the HOB list and add all resource descriptors to the GCD
2504 for (Hob
.Raw
= *HobStart
; !END_OF_HOB_LIST(Hob
); Hob
.Raw
= GET_NEXT_HOB(Hob
)) {
2506 GcdMemoryType
= EfiGcdMemoryTypeNonExistent
;
2507 GcdIoType
= EfiGcdIoTypeNonExistent
;
2509 if (GET_HOB_TYPE (Hob
) == EFI_HOB_TYPE_RESOURCE_DESCRIPTOR
) {
2511 ResourceHob
= Hob
.ResourceDescriptor
;
2513 switch (ResourceHob
->ResourceType
) {
2514 case EFI_RESOURCE_SYSTEM_MEMORY
:
2515 if ((ResourceHob
->ResourceAttribute
& MEMORY_ATTRIBUTE_MASK
) == TESTED_MEMORY_ATTRIBUTES
) {
2516 if ((ResourceHob
->ResourceAttribute
& EFI_RESOURCE_ATTRIBUTE_MORE_RELIABLE
) == EFI_RESOURCE_ATTRIBUTE_MORE_RELIABLE
) {
2517 GcdMemoryType
= EfiGcdMemoryTypeMoreReliable
;
2519 GcdMemoryType
= EfiGcdMemoryTypeSystemMemory
;
2522 if ((ResourceHob
->ResourceAttribute
& MEMORY_ATTRIBUTE_MASK
) == INITIALIZED_MEMORY_ATTRIBUTES
) {
2523 GcdMemoryType
= EfiGcdMemoryTypeReserved
;
2525 if ((ResourceHob
->ResourceAttribute
& MEMORY_ATTRIBUTE_MASK
) == PRESENT_MEMORY_ATTRIBUTES
) {
2526 GcdMemoryType
= EfiGcdMemoryTypeReserved
;
2528 if ((ResourceHob
->ResourceAttribute
& EFI_RESOURCE_ATTRIBUTE_PERSISTENT
) == EFI_RESOURCE_ATTRIBUTE_PERSISTENT
) {
2529 GcdMemoryType
= EfiGcdMemoryTypePersistent
;
2532 case EFI_RESOURCE_MEMORY_MAPPED_IO
:
2533 case EFI_RESOURCE_FIRMWARE_DEVICE
:
2534 GcdMemoryType
= EfiGcdMemoryTypeMemoryMappedIo
;
2536 case EFI_RESOURCE_MEMORY_MAPPED_IO_PORT
:
2537 case EFI_RESOURCE_MEMORY_RESERVED
:
2538 GcdMemoryType
= EfiGcdMemoryTypeReserved
;
2540 case EFI_RESOURCE_IO
:
2541 GcdIoType
= EfiGcdIoTypeIo
;
2543 case EFI_RESOURCE_IO_RESERVED
:
2544 GcdIoType
= EfiGcdIoTypeReserved
;
2548 if (GcdMemoryType
!= EfiGcdMemoryTypeNonExistent
) {
2550 // Validate the Resource HOB Attributes
2552 CoreValidateResourceDescriptorHobAttributes (ResourceHob
->ResourceAttribute
);
2555 // Convert the Resource HOB Attributes to an EFI Memory Capabilities mask
2557 Capabilities
= CoreConvertResourceDescriptorHobAttributesToCapabilities (
2559 ResourceHob
->ResourceAttribute
2562 Status
= CoreInternalAddMemorySpace (
2564 ResourceHob
->PhysicalStart
,
2565 ResourceHob
->ResourceLength
,
2570 if (GcdIoType
!= EfiGcdIoTypeNonExistent
) {
2571 Status
= CoreAddIoSpace (
2573 ResourceHob
->PhysicalStart
,
2574 ResourceHob
->ResourceLength
2581 // Allocate first memory region from the GCD by the DXE core
2583 Status
= CoreGetMemorySpaceDescriptor (MemoryBaseAddress
, &Descriptor
);
2584 if (!EFI_ERROR (Status
)) {
2585 ASSERT ((Descriptor
.GcdMemoryType
== EfiGcdMemoryTypeSystemMemory
) ||
2586 (Descriptor
.GcdMemoryType
== EfiGcdMemoryTypeMoreReliable
));
2587 Status
= CoreAllocateMemorySpace (
2588 EfiGcdAllocateAddress
,
2589 Descriptor
.GcdMemoryType
,
2593 gDxeCoreImageHandle
,
2599 // Walk the HOB list and allocate all memory space that is consumed by memory allocation HOBs,
2600 // and Firmware Volume HOBs. Also update the EFI Memory Map with the memory allocation HOBs.
2602 for (Hob
.Raw
= *HobStart
; !END_OF_HOB_LIST(Hob
); Hob
.Raw
= GET_NEXT_HOB(Hob
)) {
2603 if (GET_HOB_TYPE (Hob
) == EFI_HOB_TYPE_MEMORY_ALLOCATION
) {
2604 MemoryHob
= Hob
.MemoryAllocation
;
2605 BaseAddress
= MemoryHob
->AllocDescriptor
.MemoryBaseAddress
;
2606 Status
= CoreGetMemorySpaceDescriptor (BaseAddress
, &Descriptor
);
2607 if (!EFI_ERROR (Status
)) {
2608 Status
= CoreAllocateMemorySpace (
2609 EfiGcdAllocateAddress
,
2610 Descriptor
.GcdMemoryType
,
2612 MemoryHob
->AllocDescriptor
.MemoryLength
,
2614 gDxeCoreImageHandle
,
2617 if (!EFI_ERROR (Status
) &&
2618 ((Descriptor
.GcdMemoryType
== EfiGcdMemoryTypeSystemMemory
) ||
2619 (Descriptor
.GcdMemoryType
== EfiGcdMemoryTypeMoreReliable
))) {
2620 CoreAddMemoryDescriptor (
2621 MemoryHob
->AllocDescriptor
.MemoryType
,
2622 MemoryHob
->AllocDescriptor
.MemoryBaseAddress
,
2623 RShiftU64 (MemoryHob
->AllocDescriptor
.MemoryLength
, EFI_PAGE_SHIFT
),
2624 Descriptor
.Capabilities
& (~EFI_MEMORY_RUNTIME
)
2630 if (GET_HOB_TYPE (Hob
) == EFI_HOB_TYPE_FV
) {
2631 FirmwareVolumeHob
= Hob
.FirmwareVolume
;
2632 BaseAddress
= FirmwareVolumeHob
->BaseAddress
;
2633 Status
= CoreAllocateMemorySpace (
2634 EfiGcdAllocateAddress
,
2635 EfiGcdMemoryTypeMemoryMappedIo
,
2637 FirmwareVolumeHob
->Length
,
2639 gDxeCoreImageHandle
,
2646 // Add and allocate the remaining unallocated system memory to the memory services.
2648 Status
= CoreGetMemorySpaceMap (&NumberOfDescriptors
, &MemorySpaceMap
);
2649 ASSERT (Status
== EFI_SUCCESS
);
2651 MemorySpaceMapHobList
= NULL
;
2652 for (Index
= 0; Index
< NumberOfDescriptors
; Index
++) {
2653 if ((MemorySpaceMap
[Index
].GcdMemoryType
== EfiGcdMemoryTypeSystemMemory
) ||
2654 (MemorySpaceMap
[Index
].GcdMemoryType
== EfiGcdMemoryTypeMoreReliable
)) {
2655 if (MemorySpaceMap
[Index
].ImageHandle
== NULL
) {
2656 BaseAddress
= PageAlignAddress (MemorySpaceMap
[Index
].BaseAddress
);
2657 Length
= PageAlignLength (MemorySpaceMap
[Index
].BaseAddress
+ MemorySpaceMap
[Index
].Length
- BaseAddress
);
2658 if (Length
== 0 || MemorySpaceMap
[Index
].BaseAddress
+ MemorySpaceMap
[Index
].Length
< BaseAddress
) {
2661 if (((UINTN
) MemorySpaceMap
[Index
].BaseAddress
<= (UINTN
) (*HobStart
)) &&
2662 ((UINTN
) (MemorySpaceMap
[Index
].BaseAddress
+ MemorySpaceMap
[Index
].Length
) >= (UINTN
) PhitHob
->EfiFreeMemoryBottom
)) {
2664 // Skip the memory space that covers HOB List, it should be processed
2665 // after HOB List relocation to avoid the resources allocated by others
2666 // to corrupt HOB List before its relocation.
2668 MemorySpaceMapHobList
= &MemorySpaceMap
[Index
];
2671 CoreAddMemoryDescriptor (
2672 EfiConventionalMemory
,
2674 RShiftU64 (Length
, EFI_PAGE_SHIFT
),
2675 MemorySpaceMap
[Index
].Capabilities
& (~EFI_MEMORY_RUNTIME
)
2677 Status
= CoreAllocateMemorySpace (
2678 EfiGcdAllocateAddress
,
2679 MemorySpaceMap
[Index
].GcdMemoryType
,
2683 gDxeCoreImageHandle
,
2691 // Relocate HOB List to an allocated pool buffer.
2692 // The relocation should be at after all the tested memory resources added
2693 // (except the memory space that covers HOB List) to the memory services,
2694 // because the memory resource found in CoreInitializeMemoryServices()
2695 // may have not enough remaining resource for HOB List.
2697 NewHobList
= AllocateCopyPool (
2698 (UINTN
) PhitHob
->EfiFreeMemoryBottom
- (UINTN
) (*HobStart
),
2701 ASSERT (NewHobList
!= NULL
);
2703 *HobStart
= NewHobList
;
2704 gHobList
= NewHobList
;
2706 if (MemorySpaceMapHobList
!= NULL
) {
2708 // Add and allocate the memory space that covers HOB List to the memory services
2709 // after HOB List relocation.
2711 BaseAddress
= PageAlignAddress (MemorySpaceMapHobList
->BaseAddress
);
2712 Length
= PageAlignLength (MemorySpaceMapHobList
->BaseAddress
+ MemorySpaceMapHobList
->Length
- BaseAddress
);
2713 CoreAddMemoryDescriptor (
2714 EfiConventionalMemory
,
2716 RShiftU64 (Length
, EFI_PAGE_SHIFT
),
2717 MemorySpaceMapHobList
->Capabilities
& (~EFI_MEMORY_RUNTIME
)
2719 Status
= CoreAllocateMemorySpace (
2720 EfiGcdAllocateAddress
,
2721 MemorySpaceMapHobList
->GcdMemoryType
,
2725 gDxeCoreImageHandle
,
2730 CoreFreePool (MemorySpaceMap
);