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
11 #include <Pi/PrePiDxeCis.h>
12 #include <Pi/PrePiHob.h>
15 #include "Mem/HeapGuard.h"
17 #define MINIMUM_INITIAL_MEMORY_SIZE 0x10000
19 #define MEMORY_ATTRIBUTE_MASK (EFI_RESOURCE_ATTRIBUTE_PRESENT | \
20 EFI_RESOURCE_ATTRIBUTE_INITIALIZED | \
21 EFI_RESOURCE_ATTRIBUTE_TESTED | \
22 EFI_RESOURCE_ATTRIBUTE_READ_PROTECTED | \
23 EFI_RESOURCE_ATTRIBUTE_WRITE_PROTECTED | \
24 EFI_RESOURCE_ATTRIBUTE_EXECUTION_PROTECTED | \
25 EFI_RESOURCE_ATTRIBUTE_READ_ONLY_PROTECTED | \
26 EFI_RESOURCE_ATTRIBUTE_16_BIT_IO | \
27 EFI_RESOURCE_ATTRIBUTE_32_BIT_IO | \
28 EFI_RESOURCE_ATTRIBUTE_64_BIT_IO | \
29 EFI_RESOURCE_ATTRIBUTE_PERSISTENT )
31 #define TESTED_MEMORY_ATTRIBUTES (EFI_RESOURCE_ATTRIBUTE_PRESENT | \
32 EFI_RESOURCE_ATTRIBUTE_INITIALIZED | \
33 EFI_RESOURCE_ATTRIBUTE_TESTED )
35 #define INITIALIZED_MEMORY_ATTRIBUTES (EFI_RESOURCE_ATTRIBUTE_PRESENT |\
36 EFI_RESOURCE_ATTRIBUTE_INITIALIZED )
38 #define PRESENT_MEMORY_ATTRIBUTES (EFI_RESOURCE_ATTRIBUTE_PRESENT)
43 EFI_LOCK mGcdMemorySpaceLock
= EFI_INITIALIZE_LOCK_VARIABLE (TPL_NOTIFY
);
44 EFI_LOCK mGcdIoSpaceLock
= EFI_INITIALIZE_LOCK_VARIABLE (TPL_NOTIFY
);
45 LIST_ENTRY mGcdMemorySpaceMap
= INITIALIZE_LIST_HEAD_VARIABLE (mGcdMemorySpaceMap
);
46 LIST_ENTRY mGcdIoSpaceMap
= INITIALIZE_LIST_HEAD_VARIABLE (mGcdIoSpaceMap
);
48 EFI_GCD_MAP_ENTRY mGcdMemorySpaceMapEntryTemplate
= {
49 EFI_GCD_MAP_SIGNATURE
,
58 EfiGcdMemoryTypeNonExistent
,
64 EFI_GCD_MAP_ENTRY mGcdIoSpaceMapEntryTemplate
= {
65 EFI_GCD_MAP_SIGNATURE
,
74 (EFI_GCD_MEMORY_TYPE
)0,
75 EfiGcdIoTypeNonExistent
,
80 GCD_ATTRIBUTE_CONVERSION_ENTRY mAttributeConversionTable
[] = {
81 { EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE
, EFI_MEMORY_UC
, TRUE
},
82 { EFI_RESOURCE_ATTRIBUTE_UNCACHED_EXPORTED
, EFI_MEMORY_UCE
, TRUE
},
83 { EFI_RESOURCE_ATTRIBUTE_WRITE_COMBINEABLE
, EFI_MEMORY_WC
, TRUE
},
84 { EFI_RESOURCE_ATTRIBUTE_WRITE_THROUGH_CACHEABLE
, EFI_MEMORY_WT
, TRUE
},
85 { EFI_RESOURCE_ATTRIBUTE_WRITE_BACK_CACHEABLE
, EFI_MEMORY_WB
, TRUE
},
86 { EFI_RESOURCE_ATTRIBUTE_READ_PROTECTABLE
, EFI_MEMORY_RP
, TRUE
},
87 { EFI_RESOURCE_ATTRIBUTE_WRITE_PROTECTABLE
, EFI_MEMORY_WP
, TRUE
},
88 { EFI_RESOURCE_ATTRIBUTE_EXECUTION_PROTECTABLE
, EFI_MEMORY_XP
, TRUE
},
89 { EFI_RESOURCE_ATTRIBUTE_READ_ONLY_PROTECTABLE
, EFI_MEMORY_RO
, TRUE
},
90 { EFI_RESOURCE_ATTRIBUTE_PRESENT
, EFI_MEMORY_PRESENT
, FALSE
},
91 { EFI_RESOURCE_ATTRIBUTE_INITIALIZED
, EFI_MEMORY_INITIALIZED
, FALSE
},
92 { EFI_RESOURCE_ATTRIBUTE_TESTED
, EFI_MEMORY_TESTED
, FALSE
},
93 { EFI_RESOURCE_ATTRIBUTE_PERSISTABLE
, EFI_MEMORY_NV
, TRUE
},
94 { EFI_RESOURCE_ATTRIBUTE_MORE_RELIABLE
, EFI_MEMORY_MORE_RELIABLE
, TRUE
},
99 /// Lookup table used to print GCD Memory Space Map
101 GLOBAL_REMOVE_IF_UNREFERENCED CONST CHAR8
*mGcdMemoryTypeNames
[] = {
102 "NonExist ", // EfiGcdMemoryTypeNonExistent
103 "Reserved ", // EfiGcdMemoryTypeReserved
104 "SystemMem", // EfiGcdMemoryTypeSystemMemory
105 "MMIO ", // EfiGcdMemoryTypeMemoryMappedIo
106 "PersisMem", // EfiGcdMemoryTypePersistent
107 "MoreRelia", // EfiGcdMemoryTypeMoreReliable
108 "Unaccepte", // EFI_GCD_MEMORY_TYPE_UNACCEPTED
109 "Unknown " // EfiGcdMemoryTypeMaximum
113 /// Lookup table used to print GCD I/O Space Map
115 GLOBAL_REMOVE_IF_UNREFERENCED CONST CHAR8
*mGcdIoTypeNames
[] = {
116 "NonExist", // EfiGcdIoTypeNonExistent
117 "Reserved", // EfiGcdIoTypeReserved
118 "I/O ", // EfiGcdIoTypeIo
119 "Unknown " // EfiGcdIoTypeMaximum
123 /// Lookup table used to print GCD Allocation Types
125 GLOBAL_REMOVE_IF_UNREFERENCED CONST CHAR8
*mGcdAllocationTypeNames
[] = {
126 "AnySearchBottomUp ", // EfiGcdAllocateAnySearchBottomUp
127 "MaxAddressSearchBottomUp ", // EfiGcdAllocateMaxAddressSearchBottomUp
128 "AtAddress ", // EfiGcdAllocateAddress
129 "AnySearchTopDown ", // EfiGcdAllocateAnySearchTopDown
130 "MaxAddressSearchTopDown ", // EfiGcdAllocateMaxAddressSearchTopDown
131 "Unknown " // EfiGcdMaxAllocateType
135 Dump the entire contents if the GCD Memory Space Map using DEBUG() macros when
136 PcdDebugPrintErrorLevel has the DEBUG_GCD bit set.
138 @param InitialMap TRUE if the initial GCD Memory Map is being dumped. Otherwise, FALSE.
143 CoreDumpGcdMemorySpaceMap (
149 UINTN NumberOfDescriptors
;
150 EFI_GCD_MEMORY_SPACE_DESCRIPTOR
*MemorySpaceMap
;
153 Status
= CoreGetMemorySpaceMap (&NumberOfDescriptors
, &MemorySpaceMap
);
154 ASSERT (Status
== EFI_SUCCESS
&& MemorySpaceMap
!= NULL
);
157 DEBUG ((DEBUG_GCD
, "GCD:Initial GCD Memory Space Map\n"));
160 DEBUG ((DEBUG_GCD
, "GCDMemType Range Capabilities Attributes \n"));
161 DEBUG ((DEBUG_GCD
, "========== ================================= ================ ================\n"));
162 for (Index
= 0; Index
< NumberOfDescriptors
; Index
++) {
165 "%a %016lx-%016lx %016lx %016lx%c\n",
166 mGcdMemoryTypeNames
[MIN (MemorySpaceMap
[Index
].GcdMemoryType
, EfiGcdMemoryTypeMaximum
)],
167 MemorySpaceMap
[Index
].BaseAddress
,
168 MemorySpaceMap
[Index
].BaseAddress
+ MemorySpaceMap
[Index
].Length
- 1,
169 MemorySpaceMap
[Index
].Capabilities
,
170 MemorySpaceMap
[Index
].Attributes
,
171 MemorySpaceMap
[Index
].ImageHandle
== NULL
? ' ' : '*'
175 DEBUG ((DEBUG_GCD
, "\n"));
176 FreePool (MemorySpaceMap
);
181 Dump the entire contents if the GCD I/O Space Map using DEBUG() macros when
182 PcdDebugPrintErrorLevel has the DEBUG_GCD bit set.
184 @param InitialMap TRUE if the initial GCD I/O Map is being dumped. Otherwise, FALSE.
189 CoreDumpGcdIoSpaceMap (
195 UINTN NumberOfDescriptors
;
196 EFI_GCD_IO_SPACE_DESCRIPTOR
*IoSpaceMap
;
199 Status
= CoreGetIoSpaceMap (&NumberOfDescriptors
, &IoSpaceMap
);
200 ASSERT (Status
== EFI_SUCCESS
&& IoSpaceMap
!= NULL
);
203 DEBUG ((DEBUG_GCD
, "GCD:Initial GCD I/O Space Map\n"));
206 DEBUG ((DEBUG_GCD
, "GCDIoType Range \n"));
207 DEBUG ((DEBUG_GCD
, "========== =================================\n"));
208 for (Index
= 0; Index
< NumberOfDescriptors
; Index
++) {
211 "%a %016lx-%016lx%c\n",
212 mGcdIoTypeNames
[MIN (IoSpaceMap
[Index
].GcdIoType
, EfiGcdIoTypeMaximum
)],
213 IoSpaceMap
[Index
].BaseAddress
,
214 IoSpaceMap
[Index
].BaseAddress
+ IoSpaceMap
[Index
].Length
- 1,
215 IoSpaceMap
[Index
].ImageHandle
== NULL
? ' ' : '*'
219 DEBUG ((DEBUG_GCD
, "\n"));
220 FreePool (IoSpaceMap
);
225 Validate resource descriptor HOB's attributes.
227 If Attributes includes some memory resource's settings, it should include
228 the corresponding capabilites also.
230 @param Attributes Resource descriptor HOB attributes.
234 CoreValidateResourceDescriptorHobAttributes (
239 ((Attributes
& EFI_RESOURCE_ATTRIBUTE_READ_PROTECTED
) == 0) ||
240 ((Attributes
& EFI_RESOURCE_ATTRIBUTE_READ_PROTECTABLE
) != 0)
243 ((Attributes
& EFI_RESOURCE_ATTRIBUTE_WRITE_PROTECTED
) == 0) ||
244 ((Attributes
& EFI_RESOURCE_ATTRIBUTE_WRITE_PROTECTABLE
) != 0)
247 ((Attributes
& EFI_RESOURCE_ATTRIBUTE_EXECUTION_PROTECTED
) == 0) ||
248 ((Attributes
& EFI_RESOURCE_ATTRIBUTE_EXECUTION_PROTECTABLE
) != 0)
251 ((Attributes
& EFI_RESOURCE_ATTRIBUTE_READ_ONLY_PROTECTED
) == 0) ||
252 ((Attributes
& EFI_RESOURCE_ATTRIBUTE_READ_ONLY_PROTECTABLE
) != 0)
255 ((Attributes
& EFI_RESOURCE_ATTRIBUTE_PERSISTENT
) == 0) ||
256 ((Attributes
& EFI_RESOURCE_ATTRIBUTE_PERSISTABLE
) != 0)
261 Acquire memory lock on mGcdMemorySpaceLock.
265 CoreAcquireGcdMemoryLock (
269 CoreAcquireLock (&mGcdMemorySpaceLock
);
273 Release memory lock on mGcdMemorySpaceLock.
277 CoreReleaseGcdMemoryLock (
281 CoreReleaseLock (&mGcdMemorySpaceLock
);
285 Acquire memory lock on mGcdIoSpaceLock.
289 CoreAcquireGcdIoLock (
293 CoreAcquireLock (&mGcdIoSpaceLock
);
297 Release memory lock on mGcdIoSpaceLock.
301 CoreReleaseGcdIoLock (
305 CoreReleaseLock (&mGcdIoSpaceLock
);
309 // GCD Initialization Worker Functions
313 Aligns a value to the specified boundary.
315 @param Value 64 bit value to align
316 @param Alignment Log base 2 of the boundary to align Value to
317 @param RoundUp TRUE if Value is to be rounded up to the nearest
318 aligned boundary. FALSE is Value is to be
319 rounded down to the nearest aligned boundary.
321 @return A 64 bit value is the aligned to the value nearest Value with an alignment by Alignment.
331 UINT64 AlignmentMask
;
333 AlignmentMask
= LShiftU64 (1, Alignment
) - 1;
335 Value
+= AlignmentMask
;
338 return Value
& (~AlignmentMask
);
342 Aligns address to the page boundary.
344 @param Value 64 bit address to align
346 @return A 64 bit value is the aligned to the value nearest Value with an alignment by Alignment.
354 return AlignValue (Value
, EFI_PAGE_SHIFT
, TRUE
);
358 Aligns length to the page boundary.
360 @param Value 64 bit length to align
362 @return A 64 bit value is the aligned to the value nearest Value with an alignment by Alignment.
370 return AlignValue (Value
, EFI_PAGE_SHIFT
, FALSE
);
374 // GCD Memory Space Worker Functions
378 Allocate pool for two entries.
380 @param TopEntry An entry of GCD map
381 @param BottomEntry An entry of GCD map
383 @retval EFI_OUT_OF_RESOURCES No enough buffer to be allocated.
384 @retval EFI_SUCCESS Both entries successfully allocated.
388 CoreAllocateGcdMapEntry (
389 IN OUT EFI_GCD_MAP_ENTRY
**TopEntry
,
390 IN OUT EFI_GCD_MAP_ENTRY
**BottomEntry
394 // Set to mOnGuarding to TRUE before memory allocation. This will make sure
395 // that the entry memory is not "guarded" by HeapGuard. Otherwise it might
396 // cause problem when it's freed (if HeapGuard is enabled).
399 *TopEntry
= AllocateZeroPool (sizeof (EFI_GCD_MAP_ENTRY
));
401 if (*TopEntry
== NULL
) {
402 return EFI_OUT_OF_RESOURCES
;
406 *BottomEntry
= AllocateZeroPool (sizeof (EFI_GCD_MAP_ENTRY
));
408 if (*BottomEntry
== NULL
) {
409 CoreFreePool (*TopEntry
);
410 return EFI_OUT_OF_RESOURCES
;
417 Internal function. Inserts a new descriptor into a sorted list
419 @param Link The linked list to insert the range BaseAddress
421 @param Entry A pointer to the entry that is inserted
422 @param BaseAddress The base address of the new range
423 @param Length The length of the new range in bytes
424 @param TopEntry Top pad entry to insert if needed.
425 @param BottomEntry Bottom pad entry to insert if needed.
427 @retval EFI_SUCCESS The new range was inserted into the linked list
431 CoreInsertGcdMapEntry (
433 IN EFI_GCD_MAP_ENTRY
*Entry
,
434 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
436 IN EFI_GCD_MAP_ENTRY
*TopEntry
,
437 IN EFI_GCD_MAP_ENTRY
*BottomEntry
440 ASSERT (Length
!= 0);
442 if (BaseAddress
> Entry
->BaseAddress
) {
443 ASSERT (BottomEntry
->Signature
== 0);
445 CopyMem (BottomEntry
, Entry
, sizeof (EFI_GCD_MAP_ENTRY
));
446 Entry
->BaseAddress
= BaseAddress
;
447 BottomEntry
->EndAddress
= BaseAddress
- 1;
448 InsertTailList (Link
, &BottomEntry
->Link
);
451 if ((BaseAddress
+ Length
- 1) < Entry
->EndAddress
) {
452 ASSERT (TopEntry
->Signature
== 0);
454 CopyMem (TopEntry
, Entry
, sizeof (EFI_GCD_MAP_ENTRY
));
455 TopEntry
->BaseAddress
= BaseAddress
+ Length
;
456 Entry
->EndAddress
= BaseAddress
+ Length
- 1;
457 InsertHeadList (Link
, &TopEntry
->Link
);
464 Merge the Gcd region specified by Link and its adjacent entry.
466 @param Link Specify the entry to be merged (with its
468 @param Forward Direction (forward or backward).
471 @retval EFI_SUCCESS Successfully returned.
472 @retval EFI_UNSUPPORTED These adjacent regions could not merge.
476 CoreMergeGcdMapEntry (
482 LIST_ENTRY
*AdjacentLink
;
483 EFI_GCD_MAP_ENTRY
*Entry
;
484 EFI_GCD_MAP_ENTRY
*AdjacentEntry
;
487 // Get adjacent entry
490 AdjacentLink
= Link
->ForwardLink
;
492 AdjacentLink
= Link
->BackLink
;
496 // If AdjacentLink is the head of the list, then no merge can be performed
498 if (AdjacentLink
== Map
) {
502 Entry
= CR (Link
, EFI_GCD_MAP_ENTRY
, Link
, EFI_GCD_MAP_SIGNATURE
);
503 AdjacentEntry
= CR (AdjacentLink
, EFI_GCD_MAP_ENTRY
, Link
, EFI_GCD_MAP_SIGNATURE
);
505 if (Entry
->Capabilities
!= AdjacentEntry
->Capabilities
) {
506 return EFI_UNSUPPORTED
;
509 if (Entry
->Attributes
!= AdjacentEntry
->Attributes
) {
510 return EFI_UNSUPPORTED
;
513 if (Entry
->GcdMemoryType
!= AdjacentEntry
->GcdMemoryType
) {
514 return EFI_UNSUPPORTED
;
517 if (Entry
->GcdIoType
!= AdjacentEntry
->GcdIoType
) {
518 return EFI_UNSUPPORTED
;
521 if (Entry
->ImageHandle
!= AdjacentEntry
->ImageHandle
) {
522 return EFI_UNSUPPORTED
;
525 if (Entry
->DeviceHandle
!= AdjacentEntry
->DeviceHandle
) {
526 return EFI_UNSUPPORTED
;
530 Entry
->EndAddress
= AdjacentEntry
->EndAddress
;
532 Entry
->BaseAddress
= AdjacentEntry
->BaseAddress
;
535 RemoveEntryList (AdjacentLink
);
536 CoreFreePool (AdjacentEntry
);
542 Merge adjacent entries on total chain.
544 @param TopEntry Top entry of GCD map.
545 @param BottomEntry Bottom entry of GCD map.
546 @param StartLink Start link of the list for this loop.
547 @param EndLink End link of the list for this loop.
550 @retval EFI_SUCCESS GCD map successfully cleaned up.
554 CoreCleanupGcdMapEntry (
555 IN EFI_GCD_MAP_ENTRY
*TopEntry
,
556 IN EFI_GCD_MAP_ENTRY
*BottomEntry
,
557 IN LIST_ENTRY
*StartLink
,
558 IN LIST_ENTRY
*EndLink
,
564 if (TopEntry
->Signature
== 0) {
565 CoreFreePool (TopEntry
);
568 if (BottomEntry
->Signature
== 0) {
569 CoreFreePool (BottomEntry
);
573 while (Link
!= EndLink
->ForwardLink
) {
574 CoreMergeGcdMapEntry (Link
, FALSE
, Map
);
575 Link
= Link
->ForwardLink
;
578 CoreMergeGcdMapEntry (EndLink
, TRUE
, Map
);
584 Search a segment of memory space in GCD map. The result is a range of GCD entry list.
586 @param BaseAddress The start address of the segment.
587 @param Length The length of the segment.
588 @param StartLink The first GCD entry involves this segment of
590 @param EndLink The first GCD entry involves this segment of
592 @param Map Points to the start entry to search.
594 @retval EFI_SUCCESS Successfully found the entry.
595 @retval EFI_NOT_FOUND Not found.
599 CoreSearchGcdMapEntry (
600 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
602 OUT LIST_ENTRY
**StartLink
,
603 OUT LIST_ENTRY
**EndLink
,
608 EFI_GCD_MAP_ENTRY
*Entry
;
610 ASSERT (Length
!= 0);
615 Link
= Map
->ForwardLink
;
616 while (Link
!= Map
) {
617 Entry
= CR (Link
, EFI_GCD_MAP_ENTRY
, Link
, EFI_GCD_MAP_SIGNATURE
);
618 if ((BaseAddress
>= Entry
->BaseAddress
) && (BaseAddress
<= Entry
->EndAddress
)) {
622 if (*StartLink
!= NULL
) {
623 if (((BaseAddress
+ Length
- 1) >= Entry
->BaseAddress
) &&
624 ((BaseAddress
+ Length
- 1) <= Entry
->EndAddress
))
631 Link
= Link
->ForwardLink
;
634 return EFI_NOT_FOUND
;
638 Count the amount of GCD map entries.
640 @param Map Points to the start entry to do the count loop.
646 CoreCountGcdMapEntry (
654 Link
= Map
->ForwardLink
;
655 while (Link
!= Map
) {
657 Link
= Link
->ForwardLink
;
664 Return the memory attribute specified by Attributes
666 @param Attributes A num with some attribute bits on.
668 @return The enum value of memory attribute.
672 ConverToCpuArchAttributes (
676 UINT64 CpuArchAttributes
;
678 CpuArchAttributes
= Attributes
& EFI_MEMORY_ATTRIBUTE_MASK
;
680 if ((Attributes
& EFI_MEMORY_UC
) == EFI_MEMORY_UC
) {
681 CpuArchAttributes
|= EFI_MEMORY_UC
;
682 } else if ((Attributes
& EFI_MEMORY_WC
) == EFI_MEMORY_WC
) {
683 CpuArchAttributes
|= EFI_MEMORY_WC
;
684 } else if ((Attributes
& EFI_MEMORY_WT
) == EFI_MEMORY_WT
) {
685 CpuArchAttributes
|= EFI_MEMORY_WT
;
686 } else if ((Attributes
& EFI_MEMORY_WB
) == EFI_MEMORY_WB
) {
687 CpuArchAttributes
|= EFI_MEMORY_WB
;
688 } else if ((Attributes
& EFI_MEMORY_UCE
) == EFI_MEMORY_UCE
) {
689 CpuArchAttributes
|= EFI_MEMORY_UCE
;
690 } else if ((Attributes
& EFI_MEMORY_WP
) == EFI_MEMORY_WP
) {
691 CpuArchAttributes
|= EFI_MEMORY_WP
;
694 return CpuArchAttributes
;
698 Do operation on a segment of memory space specified (add, free, remove, change attribute ...).
700 @param Operation The type of the operation
701 @param GcdMemoryType Additional information for the operation
702 @param GcdIoType Additional information for the operation
703 @param BaseAddress Start address of the segment
704 @param Length length of the segment
705 @param Capabilities The alterable attributes of a newly added entry
706 @param Attributes The attributes needs to be set
708 @retval EFI_INVALID_PARAMETER Length is 0 or address (length) not aligned when
710 @retval EFI_SUCCESS Action successfully done.
711 @retval EFI_UNSUPPORTED Could not find the proper descriptor on this
712 segment or set an upsupported attribute.
713 @retval EFI_ACCESS_DENIED Operate on an space non-exist or is used for an
715 @retval EFI_NOT_FOUND Free a non-using space or remove a non-exist
717 @retval EFI_OUT_OF_RESOURCES No buffer could be allocated.
718 @retval EFI_NOT_AVAILABLE_YET The attributes cannot be set because CPU architectural protocol
719 is not available yet.
724 IN EFI_GCD_MEMORY_TYPE GcdMemoryType
,
725 IN EFI_GCD_IO_TYPE GcdIoType
,
726 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
728 IN UINT64 Capabilities
,
735 EFI_GCD_MAP_ENTRY
*Entry
;
736 EFI_GCD_MAP_ENTRY
*TopEntry
;
737 EFI_GCD_MAP_ENTRY
*BottomEntry
;
738 LIST_ENTRY
*StartLink
;
740 UINT64 CpuArchAttributes
;
743 DEBUG ((DEBUG_GCD
, " Status = %r\n", EFI_INVALID_PARAMETER
));
744 return EFI_INVALID_PARAMETER
;
748 if ((Operation
& GCD_MEMORY_SPACE_OPERATION
) != 0) {
749 CoreAcquireGcdMemoryLock ();
750 Map
= &mGcdMemorySpaceMap
;
751 } else if ((Operation
& GCD_IO_SPACE_OPERATION
) != 0) {
752 CoreAcquireGcdIoLock ();
753 Map
= &mGcdIoSpaceMap
;
759 // Search for the list of descriptors that cover the range BaseAddress to BaseAddress+Length
761 Status
= CoreSearchGcdMapEntry (BaseAddress
, Length
, &StartLink
, &EndLink
, Map
);
762 if (EFI_ERROR (Status
)) {
763 Status
= EFI_UNSUPPORTED
;
768 ASSERT (StartLink
!= NULL
&& EndLink
!= NULL
);
771 // Verify that the list of descriptors are unallocated non-existent memory.
774 while (Link
!= EndLink
->ForwardLink
) {
775 Entry
= CR (Link
, EFI_GCD_MAP_ENTRY
, Link
, EFI_GCD_MAP_SIGNATURE
);
780 case GCD_ADD_MEMORY_OPERATION
:
781 if ((Entry
->GcdMemoryType
!= EfiGcdMemoryTypeNonExistent
) ||
782 (Entry
->ImageHandle
!= NULL
))
784 Status
= EFI_ACCESS_DENIED
;
789 case GCD_ADD_IO_OPERATION
:
790 if ((Entry
->GcdIoType
!= EfiGcdIoTypeNonExistent
) ||
791 (Entry
->ImageHandle
!= NULL
))
793 Status
= EFI_ACCESS_DENIED
;
801 case GCD_FREE_MEMORY_OPERATION
:
802 case GCD_FREE_IO_OPERATION
:
803 if (Entry
->ImageHandle
== NULL
) {
804 Status
= EFI_NOT_FOUND
;
812 case GCD_REMOVE_MEMORY_OPERATION
:
813 if (Entry
->GcdMemoryType
== EfiGcdMemoryTypeNonExistent
) {
814 Status
= EFI_NOT_FOUND
;
818 if (Entry
->ImageHandle
!= NULL
) {
819 Status
= EFI_ACCESS_DENIED
;
824 case GCD_REMOVE_IO_OPERATION
:
825 if (Entry
->GcdIoType
== EfiGcdIoTypeNonExistent
) {
826 Status
= EFI_NOT_FOUND
;
830 if (Entry
->ImageHandle
!= NULL
) {
831 Status
= EFI_ACCESS_DENIED
;
837 // Set attributes operation
839 case GCD_SET_ATTRIBUTES_MEMORY_OPERATION
:
840 if ((Attributes
& EFI_MEMORY_RUNTIME
) != 0) {
841 if (((BaseAddress
& EFI_PAGE_MASK
) != 0) || ((Length
& EFI_PAGE_MASK
) != 0)) {
842 Status
= EFI_INVALID_PARAMETER
;
847 if ((Entry
->Capabilities
& Attributes
) != Attributes
) {
848 Status
= EFI_UNSUPPORTED
;
854 // Set capabilities operation
856 case GCD_SET_CAPABILITIES_MEMORY_OPERATION
:
857 if (((BaseAddress
& EFI_PAGE_MASK
) != 0) || ((Length
& EFI_PAGE_MASK
) != 0)) {
858 Status
= EFI_INVALID_PARAMETER
;
864 // Current attributes must still be supported with new capabilities
866 if ((Capabilities
& Entry
->Attributes
) != Entry
->Attributes
) {
867 Status
= EFI_UNSUPPORTED
;
874 Link
= Link
->ForwardLink
;
878 // Allocate work space to perform this operation
880 Status
= CoreAllocateGcdMapEntry (&TopEntry
, &BottomEntry
);
881 if (EFI_ERROR (Status
)) {
882 Status
= EFI_OUT_OF_RESOURCES
;
886 ASSERT (TopEntry
!= NULL
&& BottomEntry
!= NULL
);
889 // Initialize CpuArchAttributes to suppress incorrect compiler/analyzer warnings.
891 CpuArchAttributes
= 0;
892 if (Operation
== GCD_SET_ATTRIBUTES_MEMORY_OPERATION
) {
894 // Call CPU Arch Protocol to attempt to set attributes on the range
896 CpuArchAttributes
= ConverToCpuArchAttributes (Attributes
);
898 // CPU arch attributes include page attributes and cache attributes.
899 // Only page attributes supports to be cleared, but not cache attributes.
900 // Caller is expected to use GetMemorySpaceDescriptor() to get the current
901 // attributes, AND/OR attributes, and then calls SetMemorySpaceAttributes()
902 // to set the new attributes.
903 // So 0 CPU arch attributes should not happen as memory should always have
904 // a cache attribute (no matter UC or WB, etc).
906 // Here, 0 CPU arch attributes will be filtered to be compatible with the
907 // case that caller just calls SetMemorySpaceAttributes() with none CPU
908 // arch attributes (for example, RUNTIME) as the purpose of the case is not
909 // to clear CPU arch attributes.
911 if (CpuArchAttributes
!= 0) {
913 Status
= EFI_NOT_AVAILABLE_YET
;
915 Status
= gCpu
->SetMemoryAttributes (
923 if (EFI_ERROR (Status
)) {
924 CoreFreePool (TopEntry
);
925 CoreFreePool (BottomEntry
);
932 // Convert/Insert the list of descriptors from StartLink to EndLink
935 while (Link
!= EndLink
->ForwardLink
) {
936 Entry
= CR (Link
, EFI_GCD_MAP_ENTRY
, Link
, EFI_GCD_MAP_SIGNATURE
);
937 CoreInsertGcdMapEntry (Link
, Entry
, BaseAddress
, Length
, TopEntry
, BottomEntry
);
942 case GCD_ADD_MEMORY_OPERATION
:
943 Entry
->GcdMemoryType
= GcdMemoryType
;
944 if (GcdMemoryType
== EfiGcdMemoryTypeMemoryMappedIo
) {
945 Entry
->Capabilities
= Capabilities
| EFI_MEMORY_RUNTIME
| EFI_MEMORY_PORT_IO
;
947 Entry
->Capabilities
= Capabilities
| EFI_MEMORY_RUNTIME
;
951 case GCD_ADD_IO_OPERATION
:
952 Entry
->GcdIoType
= GcdIoType
;
957 case GCD_FREE_MEMORY_OPERATION
:
958 case GCD_FREE_IO_OPERATION
:
959 Entry
->ImageHandle
= NULL
;
960 Entry
->DeviceHandle
= NULL
;
965 case GCD_REMOVE_MEMORY_OPERATION
:
966 Entry
->GcdMemoryType
= EfiGcdMemoryTypeNonExistent
;
967 Entry
->Capabilities
= 0;
969 case GCD_REMOVE_IO_OPERATION
:
970 Entry
->GcdIoType
= EfiGcdIoTypeNonExistent
;
973 // Set attributes operation
975 case GCD_SET_ATTRIBUTES_MEMORY_OPERATION
:
976 if (CpuArchAttributes
== 0) {
978 // Keep original CPU arch attributes when caller just calls
979 // SetMemorySpaceAttributes() with none CPU arch attributes (for example, RUNTIME).
981 Attributes
|= (Entry
->Attributes
& (EFI_CACHE_ATTRIBUTE_MASK
| EFI_MEMORY_ATTRIBUTE_MASK
));
984 Entry
->Attributes
= Attributes
;
987 // Set capabilities operation
989 case GCD_SET_CAPABILITIES_MEMORY_OPERATION
:
990 Entry
->Capabilities
= Capabilities
;
994 Link
= Link
->ForwardLink
;
1000 Status
= CoreCleanupGcdMapEntry (TopEntry
, BottomEntry
, StartLink
, EndLink
, Map
);
1003 DEBUG ((DEBUG_GCD
, " Status = %r\n", Status
));
1005 if ((Operation
& GCD_MEMORY_SPACE_OPERATION
) != 0) {
1006 CoreReleaseGcdMemoryLock ();
1007 CoreDumpGcdMemorySpaceMap (FALSE
);
1010 if ((Operation
& GCD_IO_SPACE_OPERATION
) != 0) {
1011 CoreReleaseGcdIoLock ();
1012 CoreDumpGcdIoSpaceMap (FALSE
);
1019 Check whether an entry could be used to allocate space.
1021 @param Operation Allocate memory or IO
1022 @param Entry The entry to be tested
1023 @param GcdMemoryType The desired memory type
1024 @param GcdIoType The desired IO type
1026 @retval EFI_NOT_FOUND The memory type does not match or there's an
1027 image handle on the entry.
1028 @retval EFI_UNSUPPORTED The operation unsupported.
1029 @retval EFI_SUCCESS It's ok for this entry to be used to allocate
1034 CoreAllocateSpaceCheckEntry (
1036 IN EFI_GCD_MAP_ENTRY
*Entry
,
1037 IN EFI_GCD_MEMORY_TYPE GcdMemoryType
,
1038 IN EFI_GCD_IO_TYPE GcdIoType
1041 if (Entry
->ImageHandle
!= NULL
) {
1042 return EFI_NOT_FOUND
;
1045 switch (Operation
) {
1046 case GCD_ALLOCATE_MEMORY_OPERATION
:
1047 if (Entry
->GcdMemoryType
!= GcdMemoryType
) {
1048 return EFI_NOT_FOUND
;
1052 case GCD_ALLOCATE_IO_OPERATION
:
1053 if (Entry
->GcdIoType
!= GcdIoType
) {
1054 return EFI_NOT_FOUND
;
1059 return EFI_UNSUPPORTED
;
1066 Allocate space on specified address and length.
1068 @param Operation The type of operation (memory or IO)
1069 @param GcdAllocateType The type of allocate operation
1070 @param GcdMemoryType The desired memory type
1071 @param GcdIoType The desired IO type
1072 @param Alignment Align with 2^Alignment
1073 @param Length Length to allocate
1074 @param BaseAddress Base address to allocate
1075 @param ImageHandle The image handle consume the allocated space.
1076 @param DeviceHandle The device handle consume the allocated space.
1078 @retval EFI_INVALID_PARAMETER Invalid parameter.
1079 @retval EFI_NOT_FOUND No descriptor for the desired space exists.
1080 @retval EFI_SUCCESS Space successfully allocated.
1086 IN EFI_GCD_ALLOCATE_TYPE GcdAllocateType
,
1087 IN EFI_GCD_MEMORY_TYPE GcdMemoryType
,
1088 IN EFI_GCD_IO_TYPE GcdIoType
,
1091 IN OUT EFI_PHYSICAL_ADDRESS
*BaseAddress
,
1092 IN EFI_HANDLE ImageHandle
,
1093 IN EFI_HANDLE DeviceHandle OPTIONAL
1097 EFI_PHYSICAL_ADDRESS AlignmentMask
;
1098 EFI_PHYSICAL_ADDRESS MaxAddress
;
1101 LIST_ENTRY
*SubLink
;
1102 EFI_GCD_MAP_ENTRY
*Entry
;
1103 EFI_GCD_MAP_ENTRY
*TopEntry
;
1104 EFI_GCD_MAP_ENTRY
*BottomEntry
;
1105 LIST_ENTRY
*StartLink
;
1106 LIST_ENTRY
*EndLink
;
1110 // Make sure parameters are valid
1112 if ((UINT32
)GcdAllocateType
>= EfiGcdMaxAllocateType
) {
1113 DEBUG ((DEBUG_GCD
, " Status = %r\n", EFI_INVALID_PARAMETER
));
1114 return EFI_INVALID_PARAMETER
;
1117 if ((UINT32
)GcdMemoryType
>= EfiGcdMemoryTypeMaximum
) {
1118 DEBUG ((DEBUG_GCD
, " Status = %r\n", EFI_INVALID_PARAMETER
));
1119 return EFI_INVALID_PARAMETER
;
1122 if ((UINT32
)GcdIoType
>= EfiGcdIoTypeMaximum
) {
1123 DEBUG ((DEBUG_GCD
, " Status = %r\n", EFI_INVALID_PARAMETER
));
1124 return EFI_INVALID_PARAMETER
;
1127 if (BaseAddress
== NULL
) {
1128 DEBUG ((DEBUG_GCD
, " Status = %r\n", EFI_INVALID_PARAMETER
));
1129 return EFI_INVALID_PARAMETER
;
1132 if (ImageHandle
== NULL
) {
1133 DEBUG ((DEBUG_GCD
, " Status = %r\n", EFI_INVALID_PARAMETER
));
1134 return EFI_INVALID_PARAMETER
;
1137 if (Alignment
>= 64) {
1138 DEBUG ((DEBUG_GCD
, " Status = %r\n", EFI_NOT_FOUND
));
1139 return EFI_NOT_FOUND
;
1143 DEBUG ((DEBUG_GCD
, " Status = %r\n", EFI_INVALID_PARAMETER
));
1144 return EFI_INVALID_PARAMETER
;
1148 if ((Operation
& GCD_MEMORY_SPACE_OPERATION
) != 0) {
1149 CoreAcquireGcdMemoryLock ();
1150 Map
= &mGcdMemorySpaceMap
;
1151 } else if ((Operation
& GCD_IO_SPACE_OPERATION
) != 0) {
1152 CoreAcquireGcdIoLock ();
1153 Map
= &mGcdIoSpaceMap
;
1162 // Compute alignment bit mask
1164 AlignmentMask
= LShiftU64 (1, Alignment
) - 1;
1166 if (GcdAllocateType
== EfiGcdAllocateAddress
) {
1168 // Verify that the BaseAddress passed in is aligned correctly
1170 if ((*BaseAddress
& AlignmentMask
) != 0) {
1171 Status
= EFI_NOT_FOUND
;
1176 // Search for the list of descriptors that cover the range BaseAddress to BaseAddress+Length
1178 Status
= CoreSearchGcdMapEntry (*BaseAddress
, Length
, &StartLink
, &EndLink
, Map
);
1179 if (EFI_ERROR (Status
)) {
1180 Status
= EFI_NOT_FOUND
;
1184 ASSERT (StartLink
!= NULL
&& EndLink
!= NULL
);
1187 // Verify that the list of descriptors are unallocated memory matching GcdMemoryType.
1190 while (Link
!= EndLink
->ForwardLink
) {
1191 Entry
= CR (Link
, EFI_GCD_MAP_ENTRY
, Link
, EFI_GCD_MAP_SIGNATURE
);
1192 Link
= Link
->ForwardLink
;
1193 Status
= CoreAllocateSpaceCheckEntry (Operation
, Entry
, GcdMemoryType
, GcdIoType
);
1194 if (EFI_ERROR (Status
)) {
1201 Entry
= CR (Map
->BackLink
, EFI_GCD_MAP_ENTRY
, Link
, EFI_GCD_MAP_SIGNATURE
);
1204 // Compute the maximum address to use in the search algorithm
1206 if ((GcdAllocateType
== EfiGcdAllocateMaxAddressSearchBottomUp
) ||
1207 (GcdAllocateType
== EfiGcdAllocateMaxAddressSearchTopDown
))
1209 MaxAddress
= *BaseAddress
;
1211 MaxAddress
= Entry
->EndAddress
;
1215 // Verify that the list of descriptors are unallocated memory matching GcdMemoryType.
1217 if ((GcdAllocateType
== EfiGcdAllocateMaxAddressSearchTopDown
) ||
1218 (GcdAllocateType
== EfiGcdAllocateAnySearchTopDown
))
1220 Link
= Map
->BackLink
;
1222 Link
= Map
->ForwardLink
;
1225 while (Link
!= Map
) {
1226 Entry
= CR (Link
, EFI_GCD_MAP_ENTRY
, Link
, EFI_GCD_MAP_SIGNATURE
);
1228 if ((GcdAllocateType
== EfiGcdAllocateMaxAddressSearchTopDown
) ||
1229 (GcdAllocateType
== EfiGcdAllocateAnySearchTopDown
))
1231 Link
= Link
->BackLink
;
1233 Link
= Link
->ForwardLink
;
1236 Status
= CoreAllocateSpaceCheckEntry (Operation
, Entry
, GcdMemoryType
, GcdIoType
);
1237 if (EFI_ERROR (Status
)) {
1241 if ((GcdAllocateType
== EfiGcdAllocateMaxAddressSearchTopDown
) ||
1242 (GcdAllocateType
== EfiGcdAllocateAnySearchTopDown
))
1244 if ((Entry
->BaseAddress
+ Length
) > MaxAddress
) {
1248 if (Length
> (Entry
->EndAddress
+ 1)) {
1249 Status
= EFI_NOT_FOUND
;
1253 if (Entry
->EndAddress
> MaxAddress
) {
1254 *BaseAddress
= MaxAddress
;
1256 *BaseAddress
= Entry
->EndAddress
;
1259 *BaseAddress
= (*BaseAddress
+ 1 - Length
) & (~AlignmentMask
);
1261 *BaseAddress
= (Entry
->BaseAddress
+ AlignmentMask
) & (~AlignmentMask
);
1262 if ((*BaseAddress
+ Length
- 1) > MaxAddress
) {
1263 Status
= EFI_NOT_FOUND
;
1269 // Search for the list of descriptors that cover the range BaseAddress to BaseAddress+Length
1271 Status
= CoreSearchGcdMapEntry (*BaseAddress
, Length
, &StartLink
, &EndLink
, Map
);
1272 if (EFI_ERROR (Status
)) {
1273 Status
= EFI_NOT_FOUND
;
1277 ASSERT (StartLink
!= NULL
&& EndLink
!= NULL
);
1281 // Verify that the list of descriptors are unallocated memory matching GcdMemoryType.
1284 SubLink
= StartLink
;
1285 while (SubLink
!= EndLink
->ForwardLink
) {
1286 Entry
= CR (SubLink
, EFI_GCD_MAP_ENTRY
, Link
, EFI_GCD_MAP_SIGNATURE
);
1287 Status
= CoreAllocateSpaceCheckEntry (Operation
, Entry
, GcdMemoryType
, GcdIoType
);
1288 if (EFI_ERROR (Status
)) {
1294 SubLink
= SubLink
->ForwardLink
;
1304 Status
= EFI_NOT_FOUND
;
1309 // Allocate work space to perform this operation
1311 Status
= CoreAllocateGcdMapEntry (&TopEntry
, &BottomEntry
);
1312 if (EFI_ERROR (Status
)) {
1313 Status
= EFI_OUT_OF_RESOURCES
;
1317 ASSERT (TopEntry
!= NULL
&& BottomEntry
!= NULL
);
1320 // Convert/Insert the list of descriptors from StartLink to EndLink
1323 while (Link
!= EndLink
->ForwardLink
) {
1324 Entry
= CR (Link
, EFI_GCD_MAP_ENTRY
, Link
, EFI_GCD_MAP_SIGNATURE
);
1325 CoreInsertGcdMapEntry (Link
, Entry
, *BaseAddress
, Length
, TopEntry
, BottomEntry
);
1326 Entry
->ImageHandle
= ImageHandle
;
1327 Entry
->DeviceHandle
= DeviceHandle
;
1328 Link
= Link
->ForwardLink
;
1334 Status
= CoreCleanupGcdMapEntry (TopEntry
, BottomEntry
, StartLink
, EndLink
, Map
);
1337 DEBUG ((DEBUG_GCD
, " Status = %r", Status
));
1338 if (!EFI_ERROR (Status
)) {
1339 DEBUG ((DEBUG_GCD
, " (BaseAddress = %016lx)", *BaseAddress
));
1342 DEBUG ((DEBUG_GCD
, "\n"));
1344 if ((Operation
& GCD_MEMORY_SPACE_OPERATION
) != 0) {
1345 CoreReleaseGcdMemoryLock ();
1346 CoreDumpGcdMemorySpaceMap (FALSE
);
1349 if ((Operation
& GCD_IO_SPACE_OPERATION
) != 0) {
1350 CoreReleaseGcdIoLock ();
1351 CoreDumpGcdIoSpaceMap (FALSE
);
1358 Add a segment of memory to GCD map.
1360 @param GcdMemoryType Memory type of the segment.
1361 @param BaseAddress Base address of the segment.
1362 @param Length Length of the segment.
1363 @param Capabilities alterable attributes of the segment.
1365 @retval EFI_INVALID_PARAMETER Invalid parameters.
1366 @retval EFI_SUCCESS Successfully add a segment of memory space.
1370 CoreInternalAddMemorySpace (
1371 IN EFI_GCD_MEMORY_TYPE GcdMemoryType
,
1372 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
1374 IN UINT64 Capabilities
1377 DEBUG ((DEBUG_GCD
, "GCD:AddMemorySpace(Base=%016lx,Length=%016lx)\n", BaseAddress
, Length
));
1378 DEBUG ((DEBUG_GCD
, " GcdMemoryType = %a\n", mGcdMemoryTypeNames
[MIN (GcdMemoryType
, EfiGcdMemoryTypeMaximum
)]));
1379 DEBUG ((DEBUG_GCD
, " Capabilities = %016lx\n", Capabilities
));
1382 // Make sure parameters are valid
1384 if ((GcdMemoryType
<= EfiGcdMemoryTypeNonExistent
) || (GcdMemoryType
>= EfiGcdMemoryTypeMaximum
)) {
1385 return EFI_INVALID_PARAMETER
;
1388 return CoreConvertSpace (GCD_ADD_MEMORY_OPERATION
, GcdMemoryType
, (EFI_GCD_IO_TYPE
)0, BaseAddress
, Length
, Capabilities
, 0);
1392 // GCD Core Services
1396 Allocates nonexistent memory, reserved memory, system memory, or memorymapped
1397 I/O resources from the global coherency domain of the processor.
1399 @param GcdAllocateType The type of allocate operation
1400 @param GcdMemoryType The desired memory type
1401 @param Alignment Align with 2^Alignment
1402 @param Length Length to allocate
1403 @param BaseAddress Base address to allocate
1404 @param ImageHandle The image handle consume the allocated space.
1405 @param DeviceHandle The device handle consume the allocated space.
1407 @retval EFI_INVALID_PARAMETER Invalid parameter.
1408 @retval EFI_NOT_FOUND No descriptor contains the desired space.
1409 @retval EFI_SUCCESS Memory space successfully allocated.
1414 CoreAllocateMemorySpace (
1415 IN EFI_GCD_ALLOCATE_TYPE GcdAllocateType
,
1416 IN EFI_GCD_MEMORY_TYPE GcdMemoryType
,
1419 IN OUT EFI_PHYSICAL_ADDRESS
*BaseAddress
,
1420 IN EFI_HANDLE ImageHandle
,
1421 IN EFI_HANDLE DeviceHandle OPTIONAL
1424 if (BaseAddress
!= NULL
) {
1425 DEBUG ((DEBUG_GCD
, "GCD:AllocateMemorySpace(Base=%016lx,Length=%016lx)\n", *BaseAddress
, Length
));
1427 DEBUG ((DEBUG_GCD
, "GCD:AllocateMemorySpace(Base=<NULL>,Length=%016lx)\n", Length
));
1430 DEBUG ((DEBUG_GCD
, " GcdAllocateType = %a\n", mGcdAllocationTypeNames
[MIN (GcdAllocateType
, EfiGcdMaxAllocateType
)]));
1431 DEBUG ((DEBUG_GCD
, " GcdMemoryType = %a\n", mGcdMemoryTypeNames
[MIN (GcdMemoryType
, EfiGcdMemoryTypeMaximum
)]));
1432 DEBUG ((DEBUG_GCD
, " Alignment = %016lx\n", LShiftU64 (1, Alignment
)));
1433 DEBUG ((DEBUG_GCD
, " ImageHandle = %p\n", ImageHandle
));
1434 DEBUG ((DEBUG_GCD
, " DeviceHandle = %p\n", DeviceHandle
));
1436 return CoreAllocateSpace (
1437 GCD_ALLOCATE_MEMORY_OPERATION
,
1450 Adds reserved memory, system memory, or memory-mapped I/O resources to the
1451 global coherency domain of the processor.
1453 @param GcdMemoryType Memory type of the memory space.
1454 @param BaseAddress Base address of the memory space.
1455 @param Length Length of the memory space.
1456 @param Capabilities alterable attributes of the memory space.
1458 @retval EFI_SUCCESS Merged this memory space into GCD map.
1463 CoreAddMemorySpace (
1464 IN EFI_GCD_MEMORY_TYPE GcdMemoryType
,
1465 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
1467 IN UINT64 Capabilities
1471 EFI_PHYSICAL_ADDRESS PageBaseAddress
;
1474 Status
= CoreInternalAddMemorySpace (GcdMemoryType
, BaseAddress
, Length
, Capabilities
);
1476 if (!EFI_ERROR (Status
) && ((GcdMemoryType
== EfiGcdMemoryTypeSystemMemory
) || (GcdMemoryType
== EfiGcdMemoryTypeMoreReliable
))) {
1477 PageBaseAddress
= PageAlignAddress (BaseAddress
);
1478 PageLength
= PageAlignLength (BaseAddress
+ Length
- PageBaseAddress
);
1480 Status
= CoreAllocateMemorySpace (
1481 EfiGcdAllocateAddress
,
1486 gDxeCoreImageHandle
,
1490 if (!EFI_ERROR (Status
)) {
1491 CoreAddMemoryDescriptor (
1492 EfiConventionalMemory
,
1494 RShiftU64 (PageLength
, EFI_PAGE_SHIFT
),
1498 for ( ; PageLength
!= 0; PageLength
-= EFI_PAGE_SIZE
, PageBaseAddress
+= EFI_PAGE_SIZE
) {
1499 Status
= CoreAllocateMemorySpace (
1500 EfiGcdAllocateAddress
,
1505 gDxeCoreImageHandle
,
1509 if (!EFI_ERROR (Status
)) {
1510 CoreAddMemoryDescriptor (
1511 EfiConventionalMemory
,
1525 Frees nonexistent memory, reserved memory, system memory, or memory-mapped
1526 I/O resources from the global coherency domain of the processor.
1528 @param BaseAddress Base address of the memory space.
1529 @param Length Length of the memory space.
1531 @retval EFI_SUCCESS Space successfully freed.
1536 CoreFreeMemorySpace (
1537 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
1541 DEBUG ((DEBUG_GCD
, "GCD:FreeMemorySpace(Base=%016lx,Length=%016lx)\n", BaseAddress
, Length
));
1543 return CoreConvertSpace (GCD_FREE_MEMORY_OPERATION
, (EFI_GCD_MEMORY_TYPE
)0, (EFI_GCD_IO_TYPE
)0, BaseAddress
, Length
, 0, 0);
1547 Removes reserved memory, system memory, or memory-mapped I/O resources from
1548 the global coherency domain of the processor.
1550 @param BaseAddress Base address of the memory space.
1551 @param Length Length of the memory space.
1553 @retval EFI_SUCCESS Successfully remove a segment of memory space.
1558 CoreRemoveMemorySpace (
1559 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
1563 DEBUG ((DEBUG_GCD
, "GCD:RemoveMemorySpace(Base=%016lx,Length=%016lx)\n", BaseAddress
, Length
));
1565 return CoreConvertSpace (GCD_REMOVE_MEMORY_OPERATION
, (EFI_GCD_MEMORY_TYPE
)0, (EFI_GCD_IO_TYPE
)0, BaseAddress
, Length
, 0, 0);
1569 Build a memory descriptor according to an entry.
1571 @param Descriptor The descriptor to be built
1572 @param Entry According to this entry
1576 BuildMemoryDescriptor (
1577 IN OUT EFI_GCD_MEMORY_SPACE_DESCRIPTOR
*Descriptor
,
1578 IN EFI_GCD_MAP_ENTRY
*Entry
1581 Descriptor
->BaseAddress
= Entry
->BaseAddress
;
1582 Descriptor
->Length
= Entry
->EndAddress
- Entry
->BaseAddress
+ 1;
1583 Descriptor
->Capabilities
= Entry
->Capabilities
;
1584 Descriptor
->Attributes
= Entry
->Attributes
;
1585 Descriptor
->GcdMemoryType
= Entry
->GcdMemoryType
;
1586 Descriptor
->ImageHandle
= Entry
->ImageHandle
;
1587 Descriptor
->DeviceHandle
= Entry
->DeviceHandle
;
1591 Retrieves the descriptor for a memory region containing a specified address.
1593 @param BaseAddress Specified start address
1594 @param Descriptor Specified length
1596 @retval EFI_INVALID_PARAMETER Invalid parameter
1597 @retval EFI_SUCCESS Successfully get memory space descriptor.
1602 CoreGetMemorySpaceDescriptor (
1603 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
1604 OUT EFI_GCD_MEMORY_SPACE_DESCRIPTOR
*Descriptor
1608 LIST_ENTRY
*StartLink
;
1609 LIST_ENTRY
*EndLink
;
1610 EFI_GCD_MAP_ENTRY
*Entry
;
1613 // Make sure parameters are valid
1615 if (Descriptor
== NULL
) {
1616 return EFI_INVALID_PARAMETER
;
1619 CoreAcquireGcdMemoryLock ();
1622 // Search for the list of descriptors that contain BaseAddress
1624 Status
= CoreSearchGcdMapEntry (BaseAddress
, 1, &StartLink
, &EndLink
, &mGcdMemorySpaceMap
);
1625 if (EFI_ERROR (Status
)) {
1626 Status
= EFI_NOT_FOUND
;
1628 ASSERT (StartLink
!= NULL
&& EndLink
!= NULL
);
1630 // Copy the contents of the found descriptor into Descriptor
1632 Entry
= CR (StartLink
, EFI_GCD_MAP_ENTRY
, Link
, EFI_GCD_MAP_SIGNATURE
);
1633 BuildMemoryDescriptor (Descriptor
, Entry
);
1636 CoreReleaseGcdMemoryLock ();
1642 Modifies the attributes for a memory region in the global coherency domain of the
1645 @param BaseAddress Specified start address
1646 @param Length Specified length
1647 @param Attributes Specified attributes
1649 @retval EFI_SUCCESS The attributes were set for the memory region.
1650 @retval EFI_INVALID_PARAMETER Length is zero.
1651 @retval EFI_UNSUPPORTED The processor does not support one or more bytes of the memory
1652 resource range specified by BaseAddress and Length.
1653 @retval EFI_UNSUPPORTED The bit mask of attributes is not support for the memory resource
1654 range specified by BaseAddress and Length.
1655 @retval EFI_ACCESS_DEFINED The attributes for the memory resource range specified by
1656 BaseAddress and Length cannot be modified.
1657 @retval EFI_OUT_OF_RESOURCES There are not enough system resources to modify the attributes of
1658 the memory resource range.
1659 @retval EFI_NOT_AVAILABLE_YET The attributes cannot be set because CPU architectural protocol is
1665 CoreSetMemorySpaceAttributes (
1666 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
1668 IN UINT64 Attributes
1671 DEBUG ((DEBUG_GCD
, "GCD:SetMemorySpaceAttributes(Base=%016lx,Length=%016lx)\n", BaseAddress
, Length
));
1672 DEBUG ((DEBUG_GCD
, " Attributes = %016lx\n", Attributes
));
1674 return CoreConvertSpace (GCD_SET_ATTRIBUTES_MEMORY_OPERATION
, (EFI_GCD_MEMORY_TYPE
)0, (EFI_GCD_IO_TYPE
)0, BaseAddress
, Length
, 0, Attributes
);
1678 Modifies the capabilities for a memory region in the global coherency domain of the
1681 @param BaseAddress The physical address that is the start address of a memory region.
1682 @param Length The size in bytes of the memory region.
1683 @param Capabilities The bit mask of capabilities that the memory region supports.
1685 @retval EFI_SUCCESS The capabilities were set for the memory region.
1686 @retval EFI_INVALID_PARAMETER Length is zero.
1687 @retval EFI_UNSUPPORTED The capabilities specified by Capabilities do not include the
1688 memory region attributes currently in use.
1689 @retval EFI_ACCESS_DENIED The capabilities for the memory resource range specified by
1690 BaseAddress and Length cannot be modified.
1691 @retval EFI_OUT_OF_RESOURCES There are not enough system resources to modify the capabilities
1692 of the memory resource range.
1696 CoreSetMemorySpaceCapabilities (
1697 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
1699 IN UINT64 Capabilities
1704 DEBUG ((DEBUG_GCD
, "GCD:CoreSetMemorySpaceCapabilities(Base=%016lx,Length=%016lx)\n", BaseAddress
, Length
));
1705 DEBUG ((DEBUG_GCD
, " Capabilities = %016lx\n", Capabilities
));
1707 Status
= CoreConvertSpace (GCD_SET_CAPABILITIES_MEMORY_OPERATION
, (EFI_GCD_MEMORY_TYPE
)0, (EFI_GCD_IO_TYPE
)0, BaseAddress
, Length
, Capabilities
, 0);
1708 if (!EFI_ERROR (Status
)) {
1709 CoreUpdateMemoryAttributes (BaseAddress
, RShiftU64 (Length
, EFI_PAGE_SHIFT
), Capabilities
& (~EFI_MEMORY_RUNTIME
));
1716 Returns a map of the memory resources in the global coherency domain of the
1719 @param NumberOfDescriptors Number of descriptors.
1720 @param MemorySpaceMap Descriptor array
1722 @retval EFI_INVALID_PARAMETER Invalid parameter
1723 @retval EFI_OUT_OF_RESOURCES No enough buffer to allocate
1724 @retval EFI_SUCCESS Successfully get memory space map.
1729 CoreGetMemorySpaceMap (
1730 OUT UINTN
*NumberOfDescriptors
,
1731 OUT EFI_GCD_MEMORY_SPACE_DESCRIPTOR
**MemorySpaceMap
1735 EFI_GCD_MAP_ENTRY
*Entry
;
1736 EFI_GCD_MEMORY_SPACE_DESCRIPTOR
*Descriptor
;
1737 UINTN DescriptorCount
;
1740 // Make sure parameters are valid
1742 if (NumberOfDescriptors
== NULL
) {
1743 return EFI_INVALID_PARAMETER
;
1746 if (MemorySpaceMap
== NULL
) {
1747 return EFI_INVALID_PARAMETER
;
1750 *NumberOfDescriptors
= 0;
1751 *MemorySpaceMap
= NULL
;
1754 // Take the lock, for entering the loop with the lock held.
1756 CoreAcquireGcdMemoryLock ();
1759 // Count descriptors. It might be done more than once because the
1760 // AllocatePool() called below has to be running outside the GCD lock.
1762 DescriptorCount
= CoreCountGcdMapEntry (&mGcdMemorySpaceMap
);
1763 if ((DescriptorCount
== *NumberOfDescriptors
) && (*MemorySpaceMap
!= NULL
)) {
1765 // Fill in the MemorySpaceMap if no memory space map change.
1767 Descriptor
= *MemorySpaceMap
;
1768 Link
= mGcdMemorySpaceMap
.ForwardLink
;
1769 while (Link
!= &mGcdMemorySpaceMap
) {
1770 Entry
= CR (Link
, EFI_GCD_MAP_ENTRY
, Link
, EFI_GCD_MAP_SIGNATURE
);
1771 BuildMemoryDescriptor (Descriptor
, Entry
);
1773 Link
= Link
->ForwardLink
;
1777 // We're done; exit the loop with the lock held.
1783 // Release the lock before memory allocation, because it might cause
1784 // GCD lock conflict in one of calling path in AllocatPool().
1786 CoreReleaseGcdMemoryLock ();
1789 // Allocate memory to store the MemorySpaceMap. Note it might be already
1790 // allocated if there's map descriptor change during memory allocation at
1793 if (*MemorySpaceMap
!= NULL
) {
1794 FreePool (*MemorySpaceMap
);
1797 *MemorySpaceMap
= AllocatePool (
1799 sizeof (EFI_GCD_MEMORY_SPACE_DESCRIPTOR
)
1801 if (*MemorySpaceMap
== NULL
) {
1802 *NumberOfDescriptors
= 0;
1803 return EFI_OUT_OF_RESOURCES
;
1807 // Save the descriptor count got before for another round of check to make
1808 // sure we won't miss any, since we have code running outside the GCD lock.
1810 *NumberOfDescriptors
= DescriptorCount
;
1812 // Re-acquire the lock, for the next iteration.
1814 CoreAcquireGcdMemoryLock ();
1818 // We exited the loop with the lock held, release it.
1820 CoreReleaseGcdMemoryLock ();
1826 Adds reserved I/O or I/O resources to the global coherency domain of the processor.
1828 @param GcdIoType IO type of the segment.
1829 @param BaseAddress Base address of the segment.
1830 @param Length Length of the segment.
1832 @retval EFI_SUCCESS Merged this segment into GCD map.
1833 @retval EFI_INVALID_PARAMETER Parameter not valid
1839 IN EFI_GCD_IO_TYPE GcdIoType
,
1840 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
1844 DEBUG ((DEBUG_GCD
, "GCD:AddIoSpace(Base=%016lx,Length=%016lx)\n", BaseAddress
, Length
));
1845 DEBUG ((DEBUG_GCD
, " GcdIoType = %a\n", mGcdIoTypeNames
[MIN (GcdIoType
, EfiGcdIoTypeMaximum
)]));
1848 // Make sure parameters are valid
1850 if ((GcdIoType
<= EfiGcdIoTypeNonExistent
) || (GcdIoType
>= EfiGcdIoTypeMaximum
)) {
1851 return EFI_INVALID_PARAMETER
;
1854 return CoreConvertSpace (GCD_ADD_IO_OPERATION
, (EFI_GCD_MEMORY_TYPE
)0, GcdIoType
, BaseAddress
, Length
, 0, 0);
1858 Allocates nonexistent I/O, reserved I/O, or I/O resources from the global coherency
1859 domain of the processor.
1861 @param GcdAllocateType The type of allocate operation
1862 @param GcdIoType The desired IO type
1863 @param Alignment Align with 2^Alignment
1864 @param Length Length to allocate
1865 @param BaseAddress Base address to allocate
1866 @param ImageHandle The image handle consume the allocated space.
1867 @param DeviceHandle The device handle consume the allocated space.
1869 @retval EFI_INVALID_PARAMETER Invalid parameter.
1870 @retval EFI_NOT_FOUND No descriptor contains the desired space.
1871 @retval EFI_SUCCESS IO space successfully allocated.
1876 CoreAllocateIoSpace (
1877 IN EFI_GCD_ALLOCATE_TYPE GcdAllocateType
,
1878 IN EFI_GCD_IO_TYPE GcdIoType
,
1881 IN OUT EFI_PHYSICAL_ADDRESS
*BaseAddress
,
1882 IN EFI_HANDLE ImageHandle
,
1883 IN EFI_HANDLE DeviceHandle OPTIONAL
1886 if (BaseAddress
!= NULL
) {
1887 DEBUG ((DEBUG_GCD
, "GCD:AllocateIoSpace(Base=%016lx,Length=%016lx)\n", *BaseAddress
, Length
));
1889 DEBUG ((DEBUG_GCD
, "GCD:AllocateIoSpace(Base=<NULL>,Length=%016lx)\n", Length
));
1892 DEBUG ((DEBUG_GCD
, " GcdAllocateType = %a\n", mGcdAllocationTypeNames
[MIN (GcdAllocateType
, EfiGcdMaxAllocateType
)]));
1893 DEBUG ((DEBUG_GCD
, " GcdIoType = %a\n", mGcdIoTypeNames
[MIN (GcdIoType
, EfiGcdIoTypeMaximum
)]));
1894 DEBUG ((DEBUG_GCD
, " Alignment = %016lx\n", LShiftU64 (1, Alignment
)));
1895 DEBUG ((DEBUG_GCD
, " ImageHandle = %p\n", ImageHandle
));
1896 DEBUG ((DEBUG_GCD
, " DeviceHandle = %p\n", DeviceHandle
));
1898 return CoreAllocateSpace (
1899 GCD_ALLOCATE_IO_OPERATION
,
1901 (EFI_GCD_MEMORY_TYPE
)0,
1912 Frees nonexistent I/O, reserved I/O, or I/O resources from the global coherency
1913 domain of the processor.
1915 @param BaseAddress Base address of the segment.
1916 @param Length Length of the segment.
1918 @retval EFI_SUCCESS Space successfully freed.
1924 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
1928 DEBUG ((DEBUG_GCD
, "GCD:FreeIoSpace(Base=%016lx,Length=%016lx)\n", BaseAddress
, Length
));
1930 return CoreConvertSpace (GCD_FREE_IO_OPERATION
, (EFI_GCD_MEMORY_TYPE
)0, (EFI_GCD_IO_TYPE
)0, BaseAddress
, Length
, 0, 0);
1934 Removes reserved I/O or I/O resources from the global coherency domain of the
1937 @param BaseAddress Base address of the segment.
1938 @param Length Length of the segment.
1940 @retval EFI_SUCCESS Successfully removed a segment of IO space.
1946 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
1950 DEBUG ((DEBUG_GCD
, "GCD:RemoveIoSpace(Base=%016lx,Length=%016lx)\n", BaseAddress
, Length
));
1952 return CoreConvertSpace (GCD_REMOVE_IO_OPERATION
, (EFI_GCD_MEMORY_TYPE
)0, (EFI_GCD_IO_TYPE
)0, BaseAddress
, Length
, 0, 0);
1956 Build a IO descriptor according to an entry.
1958 @param Descriptor The descriptor to be built
1959 @param Entry According to this entry
1964 IN EFI_GCD_IO_SPACE_DESCRIPTOR
*Descriptor
,
1965 IN EFI_GCD_MAP_ENTRY
*Entry
1968 Descriptor
->BaseAddress
= Entry
->BaseAddress
;
1969 Descriptor
->Length
= Entry
->EndAddress
- Entry
->BaseAddress
+ 1;
1970 Descriptor
->GcdIoType
= Entry
->GcdIoType
;
1971 Descriptor
->ImageHandle
= Entry
->ImageHandle
;
1972 Descriptor
->DeviceHandle
= Entry
->DeviceHandle
;
1976 Retrieves the descriptor for an I/O region containing a specified address.
1978 @param BaseAddress Specified start address
1979 @param Descriptor Specified length
1981 @retval EFI_INVALID_PARAMETER Descriptor is NULL.
1982 @retval EFI_SUCCESS Successfully get the IO space descriptor.
1987 CoreGetIoSpaceDescriptor (
1988 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
1989 OUT EFI_GCD_IO_SPACE_DESCRIPTOR
*Descriptor
1993 LIST_ENTRY
*StartLink
;
1994 LIST_ENTRY
*EndLink
;
1995 EFI_GCD_MAP_ENTRY
*Entry
;
1998 // Make sure parameters are valid
2000 if (Descriptor
== NULL
) {
2001 return EFI_INVALID_PARAMETER
;
2004 CoreAcquireGcdIoLock ();
2007 // Search for the list of descriptors that contain BaseAddress
2009 Status
= CoreSearchGcdMapEntry (BaseAddress
, 1, &StartLink
, &EndLink
, &mGcdIoSpaceMap
);
2010 if (EFI_ERROR (Status
)) {
2011 Status
= EFI_NOT_FOUND
;
2013 ASSERT (StartLink
!= NULL
&& EndLink
!= NULL
);
2015 // Copy the contents of the found descriptor into Descriptor
2017 Entry
= CR (StartLink
, EFI_GCD_MAP_ENTRY
, Link
, EFI_GCD_MAP_SIGNATURE
);
2018 BuildIoDescriptor (Descriptor
, Entry
);
2021 CoreReleaseGcdIoLock ();
2027 Returns a map of the I/O resources in the global coherency domain of the processor.
2029 @param NumberOfDescriptors Number of descriptors.
2030 @param IoSpaceMap Descriptor array
2032 @retval EFI_INVALID_PARAMETER Invalid parameter
2033 @retval EFI_OUT_OF_RESOURCES No enough buffer to allocate
2034 @retval EFI_SUCCESS Successfully get IO space map.
2040 OUT UINTN
*NumberOfDescriptors
,
2041 OUT EFI_GCD_IO_SPACE_DESCRIPTOR
**IoSpaceMap
2046 EFI_GCD_MAP_ENTRY
*Entry
;
2047 EFI_GCD_IO_SPACE_DESCRIPTOR
*Descriptor
;
2050 // Make sure parameters are valid
2052 if (NumberOfDescriptors
== NULL
) {
2053 return EFI_INVALID_PARAMETER
;
2056 if (IoSpaceMap
== NULL
) {
2057 return EFI_INVALID_PARAMETER
;
2060 CoreAcquireGcdIoLock ();
2063 // Count the number of descriptors
2065 *NumberOfDescriptors
= CoreCountGcdMapEntry (&mGcdIoSpaceMap
);
2068 // Allocate the IoSpaceMap
2070 *IoSpaceMap
= AllocatePool (*NumberOfDescriptors
* sizeof (EFI_GCD_IO_SPACE_DESCRIPTOR
));
2071 if (*IoSpaceMap
== NULL
) {
2072 Status
= EFI_OUT_OF_RESOURCES
;
2077 // Fill in the IoSpaceMap
2079 Descriptor
= *IoSpaceMap
;
2080 Link
= mGcdIoSpaceMap
.ForwardLink
;
2081 while (Link
!= &mGcdIoSpaceMap
) {
2082 Entry
= CR (Link
, EFI_GCD_MAP_ENTRY
, Link
, EFI_GCD_MAP_SIGNATURE
);
2083 BuildIoDescriptor (Descriptor
, Entry
);
2085 Link
= Link
->ForwardLink
;
2088 Status
= EFI_SUCCESS
;
2091 CoreReleaseGcdIoLock ();
2096 Converts a Resource Descriptor HOB attributes mask to an EFI Memory Descriptor
2099 @param GcdMemoryType Type of resource in the GCD memory map.
2100 @param Attributes The attribute mask in the Resource Descriptor
2103 @return The capabilities mask for an EFI Memory Descriptor.
2107 CoreConvertResourceDescriptorHobAttributesToCapabilities (
2108 EFI_GCD_MEMORY_TYPE GcdMemoryType
,
2112 UINT64 Capabilities
;
2113 GCD_ATTRIBUTE_CONVERSION_ENTRY
*Conversion
;
2116 // Convert the Resource HOB Attributes to an EFI Memory Capabilities mask
2118 for (Capabilities
= 0, Conversion
= mAttributeConversionTable
; Conversion
->Attribute
!= 0; Conversion
++) {
2119 if (Conversion
->Memory
|| ((GcdMemoryType
!= EfiGcdMemoryTypeSystemMemory
) && (GcdMemoryType
!= EfiGcdMemoryTypeMoreReliable
))) {
2120 if (Attributes
& Conversion
->Attribute
) {
2121 Capabilities
|= Conversion
->Capability
;
2126 return Capabilities
;
2130 Calculate total memory bin size neeeded.
2132 @return The total memory bin size neeeded.
2136 CalculateTotalMemoryBinSizeNeeded (
2144 // Loop through each memory type in the order specified by the gMemoryTypeInformation[] array
2147 for (Index
= 0; gMemoryTypeInformation
[Index
].Type
!= EfiMaxMemoryType
; Index
++) {
2148 TotalSize
+= LShiftU64 (gMemoryTypeInformation
[Index
].NumberOfPages
, EFI_PAGE_SHIFT
);
2155 Find the largest region in the specified region that is not covered by an existing memory allocation
2157 @param BaseAddress On input start of the region to check.
2158 On output start of the largest free region.
2159 @param Length On input size of region to check.
2160 On output size of the largest free region.
2161 @param MemoryHob Hob pointer for the first memory allocation pointer to check
2164 FindLargestFreeRegion (
2165 IN OUT EFI_PHYSICAL_ADDRESS
*BaseAddress
,
2166 IN OUT UINT64
*Length
,
2167 IN EFI_HOB_MEMORY_ALLOCATION
*MemoryHob
2170 EFI_PHYSICAL_ADDRESS TopAddress
;
2171 EFI_PHYSICAL_ADDRESS AllocatedTop
;
2172 EFI_PHYSICAL_ADDRESS LowerBase
;
2174 EFI_PHYSICAL_ADDRESS UpperBase
;
2177 TopAddress
= *BaseAddress
+ *Length
;
2178 while (MemoryHob
!= NULL
) {
2179 AllocatedTop
= MemoryHob
->AllocDescriptor
.MemoryBaseAddress
+ MemoryHob
->AllocDescriptor
.MemoryLength
;
2181 if ((MemoryHob
->AllocDescriptor
.MemoryBaseAddress
>= *BaseAddress
) &&
2182 (AllocatedTop
<= TopAddress
))
2184 LowerBase
= *BaseAddress
;
2185 LowerSize
= MemoryHob
->AllocDescriptor
.MemoryBaseAddress
- *BaseAddress
;
2186 UpperBase
= AllocatedTop
;
2187 UpperSize
= TopAddress
- AllocatedTop
;
2189 if (LowerSize
!= 0) {
2190 FindLargestFreeRegion (&LowerBase
, &LowerSize
, (EFI_HOB_MEMORY_ALLOCATION
*)GetNextHob (EFI_HOB_TYPE_MEMORY_ALLOCATION
, GET_NEXT_HOB (MemoryHob
)));
2193 if (UpperSize
!= 0) {
2194 FindLargestFreeRegion (&UpperBase
, &UpperSize
, (EFI_HOB_MEMORY_ALLOCATION
*)GetNextHob (EFI_HOB_TYPE_MEMORY_ALLOCATION
, GET_NEXT_HOB (MemoryHob
)));
2197 if (UpperSize
>= LowerSize
) {
2198 *Length
= UpperSize
;
2199 *BaseAddress
= UpperBase
;
2201 *Length
= LowerSize
;
2202 *BaseAddress
= LowerBase
;
2208 MemoryHob
= GetNextHob (EFI_HOB_TYPE_MEMORY_ALLOCATION
, GET_NEXT_HOB (MemoryHob
));
2213 External function. Initializes memory services based on the memory
2214 descriptor HOBs. This function is responsible for priming the memory
2215 map, so memory allocations and resource allocations can be made.
2216 The first part of this function can not depend on any memory services
2217 until at least one memory descriptor is provided to the memory services.
2219 @param HobStart The start address of the HOB.
2220 @param MemoryBaseAddress Start address of memory region found to init DXE
2222 @param MemoryLength Length of memory region found to init DXE core.
2224 @retval EFI_SUCCESS Memory services successfully initialized.
2228 CoreInitializeMemoryServices (
2230 OUT EFI_PHYSICAL_ADDRESS
*MemoryBaseAddress
,
2231 OUT UINT64
*MemoryLength
2234 EFI_PEI_HOB_POINTERS Hob
;
2235 EFI_MEMORY_TYPE_INFORMATION
*EfiMemoryTypeInformation
;
2238 EFI_HOB_HANDOFF_INFO_TABLE
*PhitHob
;
2239 EFI_HOB_RESOURCE_DESCRIPTOR
*ResourceHob
;
2240 EFI_HOB_RESOURCE_DESCRIPTOR
*PhitResourceHob
;
2241 EFI_PHYSICAL_ADDRESS BaseAddress
;
2244 UINT64 Capabilities
;
2245 EFI_PHYSICAL_ADDRESS TestedMemoryBaseAddress
;
2246 UINT64 TestedMemoryLength
;
2247 EFI_PHYSICAL_ADDRESS HighAddress
;
2248 EFI_HOB_GUID_TYPE
*GuidHob
;
2249 UINT32 ReservedCodePageNumber
;
2250 UINT64 MinimalMemorySizeNeeded
;
2253 // Point at the first HOB. This must be the PHIT HOB.
2255 Hob
.Raw
= *HobStart
;
2256 ASSERT (GET_HOB_TYPE (Hob
) == EFI_HOB_TYPE_HANDOFF
);
2259 // Initialize the spin locks and maps in the memory services.
2260 // Also fill in the memory services into the EFI Boot Services Table
2262 CoreInitializePool ();
2265 // Initialize Local Variables
2267 PhitResourceHob
= NULL
;
2274 // Cache the PHIT HOB for later use
2276 PhitHob
= Hob
.HandoffInformationTable
;
2278 if (PcdGet64 (PcdLoadModuleAtFixAddressEnable
) != 0) {
2279 ReservedCodePageNumber
= PcdGet32 (PcdLoadFixAddressRuntimeCodePageNumber
);
2280 ReservedCodePageNumber
+= PcdGet32 (PcdLoadFixAddressBootTimeCodePageNumber
);
2283 // cache the Top address for loading modules at Fixed Address
2285 gLoadModuleAtFixAddressConfigurationTable
.DxeCodeTopAddress
= PhitHob
->EfiMemoryTop
2286 + EFI_PAGES_TO_SIZE (ReservedCodePageNumber
);
2290 // See if a Memory Type Information HOB is available
2292 GuidHob
= GetFirstGuidHob (&gEfiMemoryTypeInformationGuid
);
2293 if (GuidHob
!= NULL
) {
2294 EfiMemoryTypeInformation
= GET_GUID_HOB_DATA (GuidHob
);
2295 DataSize
= GET_GUID_HOB_DATA_SIZE (GuidHob
);
2296 if ((EfiMemoryTypeInformation
!= NULL
) && (DataSize
> 0) && (DataSize
<= (EfiMaxMemoryType
+ 1) * sizeof (EFI_MEMORY_TYPE_INFORMATION
))) {
2297 CopyMem (&gMemoryTypeInformation
, EfiMemoryTypeInformation
, DataSize
);
2302 // Include the total memory bin size needed to make sure memory bin could be allocated successfully.
2304 MinimalMemorySizeNeeded
= MINIMUM_INITIAL_MEMORY_SIZE
+ CalculateTotalMemoryBinSizeNeeded ();
2307 // Find the Resource Descriptor HOB that contains PHIT range EfiFreeMemoryBottom..EfiFreeMemoryTop
2310 for (Hob
.Raw
= *HobStart
; !END_OF_HOB_LIST (Hob
); Hob
.Raw
= GET_NEXT_HOB (Hob
)) {
2312 // Skip all HOBs except Resource Descriptor HOBs
2314 if (GET_HOB_TYPE (Hob
) != EFI_HOB_TYPE_RESOURCE_DESCRIPTOR
) {
2319 // Skip Resource Descriptor HOBs that do not describe tested system memory
2321 ResourceHob
= Hob
.ResourceDescriptor
;
2322 if (ResourceHob
->ResourceType
!= EFI_RESOURCE_SYSTEM_MEMORY
) {
2326 if ((ResourceHob
->ResourceAttribute
& MEMORY_ATTRIBUTE_MASK
) != TESTED_MEMORY_ATTRIBUTES
) {
2331 // Skip Resource Descriptor HOBs that do not contain the PHIT range EfiFreeMemoryBottom..EfiFreeMemoryTop
2333 if (PhitHob
->EfiFreeMemoryBottom
< ResourceHob
->PhysicalStart
) {
2337 if (PhitHob
->EfiFreeMemoryTop
> (ResourceHob
->PhysicalStart
+ ResourceHob
->ResourceLength
)) {
2342 // Cache the resource descriptor HOB for the memory region described by the PHIT HOB
2344 PhitResourceHob
= ResourceHob
;
2348 // Compute range between PHIT EfiMemoryTop and the end of the Resource Descriptor HOB
2350 Attributes
= PhitResourceHob
->ResourceAttribute
;
2351 BaseAddress
= PageAlignAddress (PhitHob
->EfiMemoryTop
);
2352 Length
= PageAlignLength (ResourceHob
->PhysicalStart
+ ResourceHob
->ResourceLength
- BaseAddress
);
2353 FindLargestFreeRegion (&BaseAddress
, &Length
, (EFI_HOB_MEMORY_ALLOCATION
*)GetFirstHob (EFI_HOB_TYPE_MEMORY_ALLOCATION
));
2354 if (Length
< MinimalMemorySizeNeeded
) {
2356 // If that range is not large enough to intialize the DXE Core, then
2357 // Compute range between PHIT EfiFreeMemoryBottom and PHIT EfiFreeMemoryTop
2359 BaseAddress
= PageAlignAddress (PhitHob
->EfiFreeMemoryBottom
);
2360 Length
= PageAlignLength (PhitHob
->EfiFreeMemoryTop
- BaseAddress
);
2361 // This region is required to have no memory allocation inside it, skip check for entries in HOB List
2362 if (Length
< MinimalMemorySizeNeeded
) {
2364 // If that range is not large enough to intialize the DXE Core, then
2365 // Compute range between the start of the Resource Descriptor HOB and the start of the HOB List
2367 BaseAddress
= PageAlignAddress (ResourceHob
->PhysicalStart
);
2368 Length
= PageAlignLength ((UINT64
)((UINTN
)*HobStart
- BaseAddress
));
2369 FindLargestFreeRegion (&BaseAddress
, &Length
, (EFI_HOB_MEMORY_ALLOCATION
*)GetFirstHob (EFI_HOB_TYPE_MEMORY_ALLOCATION
));
2377 // Assert if a resource descriptor HOB for the memory region described by the PHIT was not found
2382 // Take the range in the resource descriptor HOB for the memory region described
2383 // by the PHIT as higher priority if it is big enough. It can make the memory bin
2384 // allocated to be at the same memory region with PHIT that has more better compatibility
2385 // to avoid memory fragmentation for some code practices assume and allocate <4G ACPI memory.
2387 if (Length
< MinimalMemorySizeNeeded
) {
2389 // Search all the resource descriptor HOBs from the highest possible addresses down for a memory
2390 // region that is big enough to initialize the DXE core. Always skip the PHIT Resource HOB.
2391 // The max address must be within the physically addressible range for the processor.
2393 HighAddress
= MAX_ALLOC_ADDRESS
;
2394 for (Hob
.Raw
= *HobStart
; !END_OF_HOB_LIST (Hob
); Hob
.Raw
= GET_NEXT_HOB (Hob
)) {
2396 // Skip the Resource Descriptor HOB that contains the PHIT
2398 if (Hob
.ResourceDescriptor
== PhitResourceHob
) {
2403 // Skip all HOBs except Resource Descriptor HOBs
2405 if (GET_HOB_TYPE (Hob
) != EFI_HOB_TYPE_RESOURCE_DESCRIPTOR
) {
2410 // Skip Resource Descriptor HOBs that do not describe tested system memory below MAX_ALLOC_ADDRESS
2412 ResourceHob
= Hob
.ResourceDescriptor
;
2413 if (ResourceHob
->ResourceType
!= EFI_RESOURCE_SYSTEM_MEMORY
) {
2417 if ((ResourceHob
->ResourceAttribute
& MEMORY_ATTRIBUTE_MASK
) != TESTED_MEMORY_ATTRIBUTES
) {
2421 if ((ResourceHob
->PhysicalStart
+ ResourceHob
->ResourceLength
) > (EFI_PHYSICAL_ADDRESS
)MAX_ALLOC_ADDRESS
) {
2426 // Skip Resource Descriptor HOBs that are below a previously found Resource Descriptor HOB
2428 if ((HighAddress
!= (EFI_PHYSICAL_ADDRESS
)MAX_ALLOC_ADDRESS
) && (ResourceHob
->PhysicalStart
<= HighAddress
)) {
2433 // Skip Resource Descriptor HOBs that are not large enough to initilize the DXE Core
2435 TestedMemoryBaseAddress
= PageAlignAddress (ResourceHob
->PhysicalStart
);
2436 TestedMemoryLength
= PageAlignLength (ResourceHob
->PhysicalStart
+ ResourceHob
->ResourceLength
- TestedMemoryBaseAddress
);
2437 FindLargestFreeRegion (&TestedMemoryBaseAddress
, &TestedMemoryLength
, (EFI_HOB_MEMORY_ALLOCATION
*)GetFirstHob (EFI_HOB_TYPE_MEMORY_ALLOCATION
));
2438 if (TestedMemoryLength
< MinimalMemorySizeNeeded
) {
2443 // Save the range described by the Resource Descriptor that is large enough to initilize the DXE Core
2445 BaseAddress
= TestedMemoryBaseAddress
;
2446 Length
= TestedMemoryLength
;
2447 Attributes
= ResourceHob
->ResourceAttribute
;
2448 HighAddress
= ResourceHob
->PhysicalStart
;
2452 DEBUG ((DEBUG_INFO
, "CoreInitializeMemoryServices:\n"));
2453 DEBUG ((DEBUG_INFO
, " BaseAddress - 0x%lx Length - 0x%lx MinimalMemorySizeNeeded - 0x%lx\n", BaseAddress
, Length
, MinimalMemorySizeNeeded
));
2456 // If no memory regions are found that are big enough to initialize the DXE core, then ASSERT().
2458 ASSERT (Length
>= MinimalMemorySizeNeeded
);
2461 // Convert the Resource HOB Attributes to an EFI Memory Capabilities mask
2463 if ((Attributes
& EFI_RESOURCE_ATTRIBUTE_MORE_RELIABLE
) == EFI_RESOURCE_ATTRIBUTE_MORE_RELIABLE
) {
2464 Capabilities
= CoreConvertResourceDescriptorHobAttributesToCapabilities (EfiGcdMemoryTypeMoreReliable
, Attributes
);
2466 Capabilities
= CoreConvertResourceDescriptorHobAttributesToCapabilities (EfiGcdMemoryTypeSystemMemory
, Attributes
);
2470 // Declare the very first memory region, so the EFI Memory Services are available.
2472 CoreAddMemoryDescriptor (
2473 EfiConventionalMemory
,
2475 RShiftU64 (Length
, EFI_PAGE_SHIFT
),
2479 *MemoryBaseAddress
= BaseAddress
;
2480 *MemoryLength
= Length
;
2486 External function. Initializes the GCD and memory services based on the memory
2487 descriptor HOBs. This function is responsible for priming the GCD map and the
2488 memory map, so memory allocations and resource allocations can be made. The
2489 HobStart will be relocated to a pool buffer.
2491 @param HobStart The start address of the HOB
2492 @param MemoryBaseAddress Start address of memory region found to init DXE
2494 @param MemoryLength Length of memory region found to init DXE core.
2496 @retval EFI_SUCCESS GCD services successfully initialized.
2500 CoreInitializeGcdServices (
2501 IN OUT VOID
**HobStart
,
2502 IN EFI_PHYSICAL_ADDRESS MemoryBaseAddress
,
2503 IN UINT64 MemoryLength
2506 EFI_PEI_HOB_POINTERS Hob
;
2508 EFI_HOB_HANDOFF_INFO_TABLE
*PhitHob
;
2509 UINT8 SizeOfMemorySpace
;
2510 UINT8 SizeOfIoSpace
;
2511 EFI_HOB_RESOURCE_DESCRIPTOR
*ResourceHob
;
2512 EFI_PHYSICAL_ADDRESS BaseAddress
;
2515 EFI_GCD_MAP_ENTRY
*Entry
;
2516 EFI_GCD_MEMORY_TYPE GcdMemoryType
;
2517 EFI_GCD_IO_TYPE GcdIoType
;
2518 EFI_GCD_MEMORY_SPACE_DESCRIPTOR Descriptor
;
2519 EFI_HOB_MEMORY_ALLOCATION
*MemoryHob
;
2520 EFI_HOB_FIRMWARE_VOLUME
*FirmwareVolumeHob
;
2521 UINTN NumberOfDescriptors
;
2522 EFI_GCD_MEMORY_SPACE_DESCRIPTOR
*MemorySpaceMap
;
2524 UINT64 Capabilities
;
2525 EFI_HOB_CPU
*CpuHob
;
2526 EFI_GCD_MEMORY_SPACE_DESCRIPTOR
*MemorySpaceMapHobList
;
2529 // Cache the PHIT HOB for later use
2531 PhitHob
= (EFI_HOB_HANDOFF_INFO_TABLE
*)(*HobStart
);
2534 // Get the number of address lines in the I/O and Memory space for the CPU
2536 CpuHob
= GetFirstHob (EFI_HOB_TYPE_CPU
);
2537 ASSERT (CpuHob
!= NULL
);
2538 SizeOfMemorySpace
= CpuHob
->SizeOfMemorySpace
;
2539 SizeOfIoSpace
= CpuHob
->SizeOfIoSpace
;
2542 // Initialize the GCD Memory Space Map
2544 Entry
= AllocateCopyPool (sizeof (EFI_GCD_MAP_ENTRY
), &mGcdMemorySpaceMapEntryTemplate
);
2545 ASSERT (Entry
!= NULL
);
2547 Entry
->EndAddress
= LShiftU64 (1, SizeOfMemorySpace
) - 1;
2549 InsertHeadList (&mGcdMemorySpaceMap
, &Entry
->Link
);
2551 CoreDumpGcdMemorySpaceMap (TRUE
);
2554 // Initialize the GCD I/O Space Map
2556 Entry
= AllocateCopyPool (sizeof (EFI_GCD_MAP_ENTRY
), &mGcdIoSpaceMapEntryTemplate
);
2557 ASSERT (Entry
!= NULL
);
2559 Entry
->EndAddress
= LShiftU64 (1, SizeOfIoSpace
) - 1;
2561 InsertHeadList (&mGcdIoSpaceMap
, &Entry
->Link
);
2563 CoreDumpGcdIoSpaceMap (TRUE
);
2566 // Walk the HOB list and add all resource descriptors to the GCD
2568 for (Hob
.Raw
= *HobStart
; !END_OF_HOB_LIST (Hob
); Hob
.Raw
= GET_NEXT_HOB (Hob
)) {
2569 GcdMemoryType
= EfiGcdMemoryTypeNonExistent
;
2570 GcdIoType
= EfiGcdIoTypeNonExistent
;
2572 if (GET_HOB_TYPE (Hob
) == EFI_HOB_TYPE_RESOURCE_DESCRIPTOR
) {
2573 ResourceHob
= Hob
.ResourceDescriptor
;
2575 switch (ResourceHob
->ResourceType
) {
2576 case EFI_RESOURCE_SYSTEM_MEMORY
:
2577 if ((ResourceHob
->ResourceAttribute
& MEMORY_ATTRIBUTE_MASK
) == TESTED_MEMORY_ATTRIBUTES
) {
2578 if ((ResourceHob
->ResourceAttribute
& EFI_RESOURCE_ATTRIBUTE_MORE_RELIABLE
) == EFI_RESOURCE_ATTRIBUTE_MORE_RELIABLE
) {
2579 GcdMemoryType
= EfiGcdMemoryTypeMoreReliable
;
2581 GcdMemoryType
= EfiGcdMemoryTypeSystemMemory
;
2585 if ((ResourceHob
->ResourceAttribute
& MEMORY_ATTRIBUTE_MASK
) == INITIALIZED_MEMORY_ATTRIBUTES
) {
2586 GcdMemoryType
= EfiGcdMemoryTypeReserved
;
2589 if ((ResourceHob
->ResourceAttribute
& MEMORY_ATTRIBUTE_MASK
) == PRESENT_MEMORY_ATTRIBUTES
) {
2590 GcdMemoryType
= EfiGcdMemoryTypeReserved
;
2593 if ((ResourceHob
->ResourceAttribute
& EFI_RESOURCE_ATTRIBUTE_PERSISTENT
) == EFI_RESOURCE_ATTRIBUTE_PERSISTENT
) {
2594 GcdMemoryType
= EfiGcdMemoryTypePersistent
;
2598 case EFI_RESOURCE_MEMORY_MAPPED_IO
:
2599 case EFI_RESOURCE_FIRMWARE_DEVICE
:
2600 GcdMemoryType
= EfiGcdMemoryTypeMemoryMappedIo
;
2602 case EFI_RESOURCE_MEMORY_MAPPED_IO_PORT
:
2603 case EFI_RESOURCE_MEMORY_RESERVED
:
2604 GcdMemoryType
= EfiGcdMemoryTypeReserved
;
2606 case BZ3937_EFI_RESOURCE_MEMORY_UNACCEPTED
:
2607 GcdMemoryType
= EFI_GCD_MEMORY_TYPE_UNACCEPTED
;
2609 case EFI_RESOURCE_IO
:
2610 GcdIoType
= EfiGcdIoTypeIo
;
2612 case EFI_RESOURCE_IO_RESERVED
:
2613 GcdIoType
= EfiGcdIoTypeReserved
;
2617 if (GcdMemoryType
!= EfiGcdMemoryTypeNonExistent
) {
2619 // Validate the Resource HOB Attributes
2621 CoreValidateResourceDescriptorHobAttributes (ResourceHob
->ResourceAttribute
);
2624 // Convert the Resource HOB Attributes to an EFI Memory Capabilities mask
2626 Capabilities
= CoreConvertResourceDescriptorHobAttributesToCapabilities (
2628 ResourceHob
->ResourceAttribute
2631 Status
= CoreInternalAddMemorySpace (
2633 ResourceHob
->PhysicalStart
,
2634 ResourceHob
->ResourceLength
,
2639 if (GcdIoType
!= EfiGcdIoTypeNonExistent
) {
2640 Status
= CoreAddIoSpace (
2642 ResourceHob
->PhysicalStart
,
2643 ResourceHob
->ResourceLength
2650 // Allocate first memory region from the GCD by the DXE core
2652 Status
= CoreGetMemorySpaceDescriptor (MemoryBaseAddress
, &Descriptor
);
2653 if (!EFI_ERROR (Status
)) {
2655 (Descriptor
.GcdMemoryType
== EfiGcdMemoryTypeSystemMemory
) ||
2656 (Descriptor
.GcdMemoryType
== EfiGcdMemoryTypeMoreReliable
)
2658 Status
= CoreAllocateMemorySpace (
2659 EfiGcdAllocateAddress
,
2660 Descriptor
.GcdMemoryType
,
2664 gDxeCoreImageHandle
,
2670 // Walk the HOB list and allocate all memory space that is consumed by memory allocation HOBs,
2671 // and Firmware Volume HOBs. Also update the EFI Memory Map with the memory allocation HOBs.
2673 for (Hob
.Raw
= *HobStart
; !END_OF_HOB_LIST (Hob
); Hob
.Raw
= GET_NEXT_HOB (Hob
)) {
2674 if (GET_HOB_TYPE (Hob
) == EFI_HOB_TYPE_MEMORY_ALLOCATION
) {
2675 MemoryHob
= Hob
.MemoryAllocation
;
2676 BaseAddress
= MemoryHob
->AllocDescriptor
.MemoryBaseAddress
;
2677 Status
= CoreGetMemorySpaceDescriptor (BaseAddress
, &Descriptor
);
2678 if (!EFI_ERROR (Status
)) {
2679 Status
= CoreAllocateMemorySpace (
2680 EfiGcdAllocateAddress
,
2681 Descriptor
.GcdMemoryType
,
2683 MemoryHob
->AllocDescriptor
.MemoryLength
,
2685 gDxeCoreImageHandle
,
2688 if (!EFI_ERROR (Status
) &&
2689 ((Descriptor
.GcdMemoryType
== EfiGcdMemoryTypeSystemMemory
) ||
2690 (Descriptor
.GcdMemoryType
== EfiGcdMemoryTypeMoreReliable
)))
2692 CoreAddMemoryDescriptor (
2693 MemoryHob
->AllocDescriptor
.MemoryType
,
2694 MemoryHob
->AllocDescriptor
.MemoryBaseAddress
,
2695 RShiftU64 (MemoryHob
->AllocDescriptor
.MemoryLength
, EFI_PAGE_SHIFT
),
2696 Descriptor
.Capabilities
& (~EFI_MEMORY_RUNTIME
)
2702 if (GET_HOB_TYPE (Hob
) == EFI_HOB_TYPE_FV
) {
2703 FirmwareVolumeHob
= Hob
.FirmwareVolume
;
2704 BaseAddress
= FirmwareVolumeHob
->BaseAddress
;
2705 Status
= CoreAllocateMemorySpace (
2706 EfiGcdAllocateAddress
,
2707 EfiGcdMemoryTypeMemoryMappedIo
,
2709 FirmwareVolumeHob
->Length
,
2711 gDxeCoreImageHandle
,
2718 // Add and allocate the remaining unallocated system memory to the memory services.
2720 Status
= CoreGetMemorySpaceMap (&NumberOfDescriptors
, &MemorySpaceMap
);
2721 ASSERT (Status
== EFI_SUCCESS
);
2723 MemorySpaceMapHobList
= NULL
;
2724 for (Index
= 0; Index
< NumberOfDescriptors
; Index
++) {
2725 if ((MemorySpaceMap
[Index
].GcdMemoryType
== EfiGcdMemoryTypeSystemMemory
) ||
2726 (MemorySpaceMap
[Index
].GcdMemoryType
== EfiGcdMemoryTypeMoreReliable
))
2728 if (MemorySpaceMap
[Index
].ImageHandle
== NULL
) {
2729 BaseAddress
= PageAlignAddress (MemorySpaceMap
[Index
].BaseAddress
);
2730 Length
= PageAlignLength (MemorySpaceMap
[Index
].BaseAddress
+ MemorySpaceMap
[Index
].Length
- BaseAddress
);
2731 if ((Length
== 0) || (MemorySpaceMap
[Index
].BaseAddress
+ MemorySpaceMap
[Index
].Length
< BaseAddress
)) {
2735 if (((UINTN
)MemorySpaceMap
[Index
].BaseAddress
<= (UINTN
)(*HobStart
)) &&
2736 ((UINTN
)(MemorySpaceMap
[Index
].BaseAddress
+ MemorySpaceMap
[Index
].Length
) >= (UINTN
)PhitHob
->EfiFreeMemoryBottom
))
2739 // Skip the memory space that covers HOB List, it should be processed
2740 // after HOB List relocation to avoid the resources allocated by others
2741 // to corrupt HOB List before its relocation.
2743 MemorySpaceMapHobList
= &MemorySpaceMap
[Index
];
2747 CoreAddMemoryDescriptor (
2748 EfiConventionalMemory
,
2750 RShiftU64 (Length
, EFI_PAGE_SHIFT
),
2751 MemorySpaceMap
[Index
].Capabilities
& (~EFI_MEMORY_RUNTIME
)
2753 Status
= CoreAllocateMemorySpace (
2754 EfiGcdAllocateAddress
,
2755 MemorySpaceMap
[Index
].GcdMemoryType
,
2759 gDxeCoreImageHandle
,
2767 // Relocate HOB List to an allocated pool buffer.
2768 // The relocation should be at after all the tested memory resources added
2769 // (except the memory space that covers HOB List) to the memory services,
2770 // because the memory resource found in CoreInitializeMemoryServices()
2771 // may have not enough remaining resource for HOB List.
2773 NewHobList
= AllocateCopyPool (
2774 (UINTN
)PhitHob
->EfiFreeMemoryBottom
- (UINTN
)(*HobStart
),
2777 ASSERT (NewHobList
!= NULL
);
2779 *HobStart
= NewHobList
;
2780 gHobList
= NewHobList
;
2782 if (MemorySpaceMapHobList
!= NULL
) {
2784 // Add and allocate the memory space that covers HOB List to the memory services
2785 // after HOB List relocation.
2787 BaseAddress
= PageAlignAddress (MemorySpaceMapHobList
->BaseAddress
);
2788 Length
= PageAlignLength (MemorySpaceMapHobList
->BaseAddress
+ MemorySpaceMapHobList
->Length
- BaseAddress
);
2789 CoreAddMemoryDescriptor (
2790 EfiConventionalMemory
,
2792 RShiftU64 (Length
, EFI_PAGE_SHIFT
),
2793 MemorySpaceMapHobList
->Capabilities
& (~EFI_MEMORY_RUNTIME
)
2795 Status
= CoreAllocateMemorySpace (
2796 EfiGcdAllocateAddress
,
2797 MemorySpaceMapHobList
->GcdMemoryType
,
2801 gDxeCoreImageHandle
,
2806 CoreFreePool (MemorySpaceMap
);