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 - 2015, Intel Corporation. All rights reserved.<BR>
7 This program and the accompanying materials
8 are licensed and made available under the terms and conditions of the BSD License
9 which accompanies this distribution. The full text of the license may be found at
10 http://opensource.org/licenses/bsd-license.php
12 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
13 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
20 #define MINIMUM_INITIAL_MEMORY_SIZE 0x10000
22 #define MEMORY_ATTRIBUTE_MASK (EFI_RESOURCE_ATTRIBUTE_PRESENT | \
23 EFI_RESOURCE_ATTRIBUTE_INITIALIZED | \
24 EFI_RESOURCE_ATTRIBUTE_TESTED | \
25 EFI_RESOURCE_ATTRIBUTE_READ_PROTECTED | \
26 EFI_RESOURCE_ATTRIBUTE_WRITE_PROTECTED | \
27 EFI_RESOURCE_ATTRIBUTE_EXECUTION_PROTECTED | \
28 EFI_RESOURCE_ATTRIBUTE_READ_ONLY_PROTECTED | \
29 EFI_RESOURCE_ATTRIBUTE_16_BIT_IO | \
30 EFI_RESOURCE_ATTRIBUTE_32_BIT_IO | \
31 EFI_RESOURCE_ATTRIBUTE_64_BIT_IO | \
32 EFI_RESOURCE_ATTRIBUTE_PERSISTENT )
34 #define TESTED_MEMORY_ATTRIBUTES (EFI_RESOURCE_ATTRIBUTE_PRESENT | \
35 EFI_RESOURCE_ATTRIBUTE_INITIALIZED | \
36 EFI_RESOURCE_ATTRIBUTE_TESTED )
38 #define INITIALIZED_MEMORY_ATTRIBUTES (EFI_RESOURCE_ATTRIBUTE_PRESENT | \
39 EFI_RESOURCE_ATTRIBUTE_INITIALIZED )
41 #define PRESENT_MEMORY_ATTRIBUTES (EFI_RESOURCE_ATTRIBUTE_PRESENT)
43 #define INVALID_CPU_ARCH_ATTRIBUTES 0xffffffff
48 EFI_LOCK mGcdMemorySpaceLock
= EFI_INITIALIZE_LOCK_VARIABLE (TPL_NOTIFY
);
49 EFI_LOCK mGcdIoSpaceLock
= EFI_INITIALIZE_LOCK_VARIABLE (TPL_NOTIFY
);
50 LIST_ENTRY mGcdMemorySpaceMap
= INITIALIZE_LIST_HEAD_VARIABLE (mGcdMemorySpaceMap
);
51 LIST_ENTRY mGcdIoSpaceMap
= INITIALIZE_LIST_HEAD_VARIABLE (mGcdIoSpaceMap
);
53 EFI_GCD_MAP_ENTRY mGcdMemorySpaceMapEntryTemplate
= {
54 EFI_GCD_MAP_SIGNATURE
,
63 EfiGcdMemoryTypeNonExistent
,
69 EFI_GCD_MAP_ENTRY mGcdIoSpaceMapEntryTemplate
= {
70 EFI_GCD_MAP_SIGNATURE
,
79 (EFI_GCD_MEMORY_TYPE
) 0,
80 EfiGcdIoTypeNonExistent
,
85 GCD_ATTRIBUTE_CONVERSION_ENTRY mAttributeConversionTable
[] = {
86 { EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE
, EFI_MEMORY_UC
, TRUE
},
87 { EFI_RESOURCE_ATTRIBUTE_UNCACHED_EXPORTED
, EFI_MEMORY_UCE
, TRUE
},
88 { EFI_RESOURCE_ATTRIBUTE_WRITE_COMBINEABLE
, EFI_MEMORY_WC
, TRUE
},
89 { EFI_RESOURCE_ATTRIBUTE_WRITE_THROUGH_CACHEABLE
, EFI_MEMORY_WT
, TRUE
},
90 { EFI_RESOURCE_ATTRIBUTE_WRITE_BACK_CACHEABLE
, EFI_MEMORY_WB
, TRUE
},
91 { EFI_RESOURCE_ATTRIBUTE_READ_PROTECTABLE
, EFI_MEMORY_RP
, TRUE
},
92 { EFI_RESOURCE_ATTRIBUTE_WRITE_PROTECTABLE
, EFI_MEMORY_WP
, TRUE
},
93 { EFI_RESOURCE_ATTRIBUTE_EXECUTION_PROTECTABLE
, EFI_MEMORY_XP
, TRUE
},
94 { EFI_RESOURCE_ATTRIBUTE_READ_ONLY_PROTECTABLE
, EFI_MEMORY_RO
, TRUE
},
95 { EFI_RESOURCE_ATTRIBUTE_PRESENT
, EFI_MEMORY_PRESENT
, FALSE
},
96 { EFI_RESOURCE_ATTRIBUTE_INITIALIZED
, EFI_MEMORY_INITIALIZED
, FALSE
},
97 { EFI_RESOURCE_ATTRIBUTE_TESTED
, EFI_MEMORY_TESTED
, FALSE
},
98 { EFI_RESOURCE_ATTRIBUTE_PERSISTABLE
, EFI_MEMORY_NV
, TRUE
},
99 { EFI_RESOURCE_ATTRIBUTE_MORE_RELIABLE
, EFI_MEMORY_MORE_RELIABLE
, TRUE
},
104 /// Lookup table used to print GCD Memory Space Map
106 GLOBAL_REMOVE_IF_UNREFERENCED CONST CHAR8
*mGcdMemoryTypeNames
[] = {
107 "NonExist ", // EfiGcdMemoryTypeNonExistent
108 "Reserved ", // EfiGcdMemoryTypeReserved
109 "SystemMem", // EfiGcdMemoryTypeSystemMemory
110 "MMIO ", // EfiGcdMemoryTypeMemoryMappedIo
111 "PersisMem", // EfiGcdMemoryTypePersistentMemory
112 "MoreRelia", // EfiGcdMemoryTypeMoreReliable
113 "Unknown " // EfiGcdMemoryTypeMaximum
117 /// Lookup table used to print GCD I/O Space Map
119 GLOBAL_REMOVE_IF_UNREFERENCED CONST CHAR8
*mGcdIoTypeNames
[] = {
120 "NonExist", // EfiGcdIoTypeNonExistent
121 "Reserved", // EfiGcdIoTypeReserved
122 "I/O ", // EfiGcdIoTypeIo
123 "Unknown " // EfiGcdIoTypeMaximum
127 /// Lookup table used to print GCD Allocation Types
129 GLOBAL_REMOVE_IF_UNREFERENCED CONST CHAR8
*mGcdAllocationTypeNames
[] = {
130 "AnySearchBottomUp ", // EfiGcdAllocateAnySearchBottomUp
131 "MaxAddressSearchBottomUp ", // EfiGcdAllocateMaxAddressSearchBottomUp
132 "AtAddress ", // EfiGcdAllocateAddress
133 "AnySearchTopDown ", // EfiGcdAllocateAnySearchTopDown
134 "MaxAddressSearchTopDown ", // EfiGcdAllocateMaxAddressSearchTopDown
135 "Unknown " // EfiGcdMaxAllocateType
139 Dump the entire contents if the GCD Memory Space Map using DEBUG() macros when
140 PcdDebugPrintErrorLevel has the DEBUG_GCD bit set.
142 @param InitialMap TRUE if the initial GCD Memory Map is being dumped. Otherwise, FALSE.
147 CoreDumpGcdMemorySpaceMap (
153 UINTN NumberOfDescriptors
;
154 EFI_GCD_MEMORY_SPACE_DESCRIPTOR
*MemorySpaceMap
;
157 Status
= CoreGetMemorySpaceMap (&NumberOfDescriptors
, &MemorySpaceMap
);
158 ASSERT (Status
== EFI_SUCCESS
&& MemorySpaceMap
!= NULL
);
161 DEBUG ((DEBUG_GCD
, "GCD:Initial GCD Memory Space Map\n"));
163 DEBUG ((DEBUG_GCD
, "GCDMemType Range Capabilities Attributes \n"));
164 DEBUG ((DEBUG_GCD
, "========== ================================= ================ ================\n"));
165 for (Index
= 0; Index
< NumberOfDescriptors
; Index
++) {
166 DEBUG ((DEBUG_GCD
, "%a %016lx-%016lx %016lx %016lx%c\n",
167 mGcdMemoryTypeNames
[MIN (MemorySpaceMap
[Index
].GcdMemoryType
, EfiGcdMemoryTypeMaximum
)],
168 MemorySpaceMap
[Index
].BaseAddress
,
169 MemorySpaceMap
[Index
].BaseAddress
+ MemorySpaceMap
[Index
].Length
- 1,
170 MemorySpaceMap
[Index
].Capabilities
,
171 MemorySpaceMap
[Index
].Attributes
,
172 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
++) {
209 DEBUG ((DEBUG_GCD
, "%a %016lx-%016lx%c\n",
210 mGcdIoTypeNames
[MIN (IoSpaceMap
[Index
].GcdIoType
, EfiGcdIoTypeMaximum
)],
211 IoSpaceMap
[Index
].BaseAddress
,
212 IoSpaceMap
[Index
].BaseAddress
+ IoSpaceMap
[Index
].Length
- 1,
213 IoSpaceMap
[Index
].ImageHandle
== NULL
? ' ' : '*'
216 DEBUG ((DEBUG_GCD
, "\n"));
217 FreePool (IoSpaceMap
);
222 Validate resource descriptor HOB's attributes.
224 If Attributes includes some memory resource's settings, it should include
225 the corresponding capabilites also.
227 @param Attributes Resource descriptor HOB attributes.
231 CoreValidateResourceDescriptorHobAttributes (
235 ASSERT (((Attributes
& EFI_RESOURCE_ATTRIBUTE_READ_PROTECTED
) == 0) ||
236 ((Attributes
& EFI_RESOURCE_ATTRIBUTE_READ_PROTECTABLE
) != 0));
237 ASSERT (((Attributes
& EFI_RESOURCE_ATTRIBUTE_WRITE_PROTECTED
) == 0) ||
238 ((Attributes
& EFI_RESOURCE_ATTRIBUTE_WRITE_PROTECTABLE
) != 0));
239 ASSERT (((Attributes
& EFI_RESOURCE_ATTRIBUTE_EXECUTION_PROTECTED
) == 0) ||
240 ((Attributes
& EFI_RESOURCE_ATTRIBUTE_EXECUTION_PROTECTABLE
) != 0));
241 ASSERT (((Attributes
& EFI_RESOURCE_ATTRIBUTE_READ_ONLY_PROTECTED
) == 0) ||
242 ((Attributes
& EFI_RESOURCE_ATTRIBUTE_READ_ONLY_PROTECTABLE
) != 0));
243 ASSERT (((Attributes
& EFI_RESOURCE_ATTRIBUTE_PERSISTENT
) == 0) ||
244 ((Attributes
& EFI_RESOURCE_ATTRIBUTE_PERSISTABLE
) != 0));
248 Acquire memory lock on mGcdMemorySpaceLock.
252 CoreAcquireGcdMemoryLock (
256 CoreAcquireLock (&mGcdMemorySpaceLock
);
262 Release memory lock on mGcdMemorySpaceLock.
266 CoreReleaseGcdMemoryLock (
270 CoreReleaseLock (&mGcdMemorySpaceLock
);
276 Acquire memory lock on mGcdIoSpaceLock.
280 CoreAcquireGcdIoLock (
284 CoreAcquireLock (&mGcdIoSpaceLock
);
289 Release memory lock on mGcdIoSpaceLock.
293 CoreReleaseGcdIoLock (
297 CoreReleaseLock (&mGcdIoSpaceLock
);
303 // GCD Initialization Worker Functions
306 Aligns a value to the specified boundary.
308 @param Value 64 bit value to align
309 @param Alignment Log base 2 of the boundary to align Value to
310 @param RoundUp TRUE if Value is to be rounded up to the nearest
311 aligned boundary. FALSE is Value is to be
312 rounded down to the nearest aligned boundary.
314 @return A 64 bit value is the aligned to the value nearest Value with an alignment by Alignment.
324 UINT64 AlignmentMask
;
326 AlignmentMask
= LShiftU64 (1, Alignment
) - 1;
328 Value
+= AlignmentMask
;
330 return Value
& (~AlignmentMask
);
335 Aligns address to the page boundary.
337 @param Value 64 bit address to align
339 @return A 64 bit value is the aligned to the value nearest Value with an alignment by Alignment.
347 return AlignValue (Value
, EFI_PAGE_SHIFT
, TRUE
);
352 Aligns length to the page boundary.
354 @param Value 64 bit length to align
356 @return A 64 bit value is the aligned to the value nearest Value with an alignment by Alignment.
364 return AlignValue (Value
, EFI_PAGE_SHIFT
, FALSE
);
368 // GCD Memory Space Worker Functions
372 Allocate pool for two entries.
374 @param TopEntry An entry of GCD map
375 @param BottomEntry An entry of GCD map
377 @retval EFI_OUT_OF_RESOURCES No enough buffer to be allocated.
378 @retval EFI_SUCCESS Both entries successfully allocated.
382 CoreAllocateGcdMapEntry (
383 IN OUT EFI_GCD_MAP_ENTRY
**TopEntry
,
384 IN OUT EFI_GCD_MAP_ENTRY
**BottomEntry
387 *TopEntry
= AllocateZeroPool (sizeof (EFI_GCD_MAP_ENTRY
));
388 if (*TopEntry
== NULL
) {
389 return EFI_OUT_OF_RESOURCES
;
392 *BottomEntry
= AllocateZeroPool (sizeof (EFI_GCD_MAP_ENTRY
));
393 if (*BottomEntry
== NULL
) {
394 CoreFreePool (*TopEntry
);
395 return EFI_OUT_OF_RESOURCES
;
403 Internal function. Inserts a new descriptor into a sorted list
405 @param Link The linked list to insert the range BaseAddress
407 @param Entry A pointer to the entry that is inserted
408 @param BaseAddress The base address of the new range
409 @param Length The length of the new range in bytes
410 @param TopEntry Top pad entry to insert if needed.
411 @param BottomEntry Bottom pad entry to insert if needed.
413 @retval EFI_SUCCESS The new range was inserted into the linked list
417 CoreInsertGcdMapEntry (
419 IN EFI_GCD_MAP_ENTRY
*Entry
,
420 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
422 IN EFI_GCD_MAP_ENTRY
*TopEntry
,
423 IN EFI_GCD_MAP_ENTRY
*BottomEntry
426 ASSERT (Length
!= 0);
428 if (BaseAddress
> Entry
->BaseAddress
) {
429 ASSERT (BottomEntry
->Signature
== 0);
431 CopyMem (BottomEntry
, Entry
, sizeof (EFI_GCD_MAP_ENTRY
));
432 Entry
->BaseAddress
= BaseAddress
;
433 BottomEntry
->EndAddress
= BaseAddress
- 1;
434 InsertTailList (Link
, &BottomEntry
->Link
);
437 if ((BaseAddress
+ Length
- 1) < Entry
->EndAddress
) {
438 ASSERT (TopEntry
->Signature
== 0);
440 CopyMem (TopEntry
, Entry
, sizeof (EFI_GCD_MAP_ENTRY
));
441 TopEntry
->BaseAddress
= BaseAddress
+ Length
;
442 Entry
->EndAddress
= BaseAddress
+ Length
- 1;
443 InsertHeadList (Link
, &TopEntry
->Link
);
451 Merge the Gcd region specified by Link and its adjacent entry.
453 @param Link Specify the entry to be merged (with its
455 @param Forward Direction (forward or backward).
458 @retval EFI_SUCCESS Successfully returned.
459 @retval EFI_UNSUPPORTED These adjacent regions could not merge.
463 CoreMergeGcdMapEntry (
469 LIST_ENTRY
*AdjacentLink
;
470 EFI_GCD_MAP_ENTRY
*Entry
;
471 EFI_GCD_MAP_ENTRY
*AdjacentEntry
;
474 // Get adjacent entry
477 AdjacentLink
= Link
->ForwardLink
;
479 AdjacentLink
= Link
->BackLink
;
483 // If AdjacentLink is the head of the list, then no merge can be performed
485 if (AdjacentLink
== Map
) {
489 Entry
= CR (Link
, EFI_GCD_MAP_ENTRY
, Link
, EFI_GCD_MAP_SIGNATURE
);
490 AdjacentEntry
= CR (AdjacentLink
, EFI_GCD_MAP_ENTRY
, Link
, EFI_GCD_MAP_SIGNATURE
);
492 if (Entry
->Capabilities
!= AdjacentEntry
->Capabilities
) {
493 return EFI_UNSUPPORTED
;
495 if (Entry
->Attributes
!= AdjacentEntry
->Attributes
) {
496 return EFI_UNSUPPORTED
;
498 if (Entry
->GcdMemoryType
!= AdjacentEntry
->GcdMemoryType
) {
499 return EFI_UNSUPPORTED
;
501 if (Entry
->GcdIoType
!= AdjacentEntry
->GcdIoType
) {
502 return EFI_UNSUPPORTED
;
504 if (Entry
->ImageHandle
!= AdjacentEntry
->ImageHandle
) {
505 return EFI_UNSUPPORTED
;
507 if (Entry
->DeviceHandle
!= AdjacentEntry
->DeviceHandle
) {
508 return EFI_UNSUPPORTED
;
512 Entry
->EndAddress
= AdjacentEntry
->EndAddress
;
514 Entry
->BaseAddress
= AdjacentEntry
->BaseAddress
;
516 RemoveEntryList (AdjacentLink
);
517 CoreFreePool (AdjacentEntry
);
524 Merge adjacent entries on total chain.
526 @param TopEntry Top entry of GCD map.
527 @param BottomEntry Bottom entry of GCD map.
528 @param StartLink Start link of the list for this loop.
529 @param EndLink End link of the list for this loop.
532 @retval EFI_SUCCESS GCD map successfully cleaned up.
536 CoreCleanupGcdMapEntry (
537 IN EFI_GCD_MAP_ENTRY
*TopEntry
,
538 IN EFI_GCD_MAP_ENTRY
*BottomEntry
,
539 IN LIST_ENTRY
*StartLink
,
540 IN LIST_ENTRY
*EndLink
,
546 if (TopEntry
->Signature
== 0) {
547 CoreFreePool (TopEntry
);
549 if (BottomEntry
->Signature
== 0) {
550 CoreFreePool (BottomEntry
);
554 while (Link
!= EndLink
->ForwardLink
) {
555 CoreMergeGcdMapEntry (Link
, FALSE
, Map
);
556 Link
= Link
->ForwardLink
;
558 CoreMergeGcdMapEntry (EndLink
, TRUE
, Map
);
565 Search a segment of memory space in GCD map. The result is a range of GCD entry list.
567 @param BaseAddress The start address of the segment.
568 @param Length The length of the segment.
569 @param StartLink The first GCD entry involves this segment of
571 @param EndLink The first GCD entry involves this segment of
573 @param Map Points to the start entry to search.
575 @retval EFI_SUCCESS Successfully found the entry.
576 @retval EFI_NOT_FOUND Not found.
580 CoreSearchGcdMapEntry (
581 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
583 OUT LIST_ENTRY
**StartLink
,
584 OUT LIST_ENTRY
**EndLink
,
589 EFI_GCD_MAP_ENTRY
*Entry
;
591 ASSERT (Length
!= 0);
596 Link
= Map
->ForwardLink
;
597 while (Link
!= Map
) {
598 Entry
= CR (Link
, EFI_GCD_MAP_ENTRY
, Link
, EFI_GCD_MAP_SIGNATURE
);
599 if (BaseAddress
>= Entry
->BaseAddress
&& BaseAddress
<= Entry
->EndAddress
) {
602 if (*StartLink
!= NULL
) {
603 if ((BaseAddress
+ Length
- 1) >= Entry
->BaseAddress
&&
604 (BaseAddress
+ Length
- 1) <= Entry
->EndAddress
) {
609 Link
= Link
->ForwardLink
;
612 return EFI_NOT_FOUND
;
617 Count the amount of GCD map entries.
619 @param Map Points to the start entry to do the count loop.
625 CoreCountGcdMapEntry (
633 Link
= Map
->ForwardLink
;
634 while (Link
!= Map
) {
636 Link
= Link
->ForwardLink
;
645 Return the memory attribute specified by Attributes
647 @param Attributes A num with some attribute bits on.
649 @return The enum value of memory attribute.
653 ConverToCpuArchAttributes (
657 if ( (Attributes
& EFI_MEMORY_UC
) == EFI_MEMORY_UC
) {
658 return EFI_MEMORY_UC
;
661 if ( (Attributes
& EFI_MEMORY_WC
) == EFI_MEMORY_WC
) {
662 return EFI_MEMORY_WC
;
665 if ( (Attributes
& EFI_MEMORY_WT
) == EFI_MEMORY_WT
) {
666 return EFI_MEMORY_WT
;
669 if ( (Attributes
& EFI_MEMORY_WB
) == EFI_MEMORY_WB
) {
670 return EFI_MEMORY_WB
;
673 if ( (Attributes
& EFI_MEMORY_WP
) == EFI_MEMORY_WP
) {
674 return EFI_MEMORY_WP
;
677 return INVALID_CPU_ARCH_ATTRIBUTES
;
683 Do operation on a segment of memory space specified (add, free, remove, change attribute ...).
685 @param Operation The type of the operation
686 @param GcdMemoryType Additional information for the operation
687 @param GcdIoType Additional information for the operation
688 @param BaseAddress Start address of the segment
689 @param Length length of the segment
690 @param Capabilities The alterable attributes of a newly added entry
691 @param Attributes The attributes needs to be set
693 @retval EFI_INVALID_PARAMETER Length is 0 or address (length) not aligned when
695 @retval EFI_SUCCESS Action successfully done.
696 @retval EFI_UNSUPPORTED Could not find the proper descriptor on this
697 segment or set an upsupported attribute.
698 @retval EFI_ACCESS_DENIED Operate on an space non-exist or is used for an
700 @retval EFI_NOT_FOUND Free a non-using space or remove a non-exist
702 @retval EFI_OUT_OF_RESOURCES No buffer could be allocated.
703 @retval EFI_NOT_AVAILABLE_YET The attributes cannot be set because CPU architectural protocol
704 is not available yet.
709 IN EFI_GCD_MEMORY_TYPE GcdMemoryType
,
710 IN EFI_GCD_IO_TYPE GcdIoType
,
711 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
713 IN UINT64 Capabilities
,
720 EFI_GCD_MAP_ENTRY
*Entry
;
721 EFI_GCD_MAP_ENTRY
*TopEntry
;
722 EFI_GCD_MAP_ENTRY
*BottomEntry
;
723 LIST_ENTRY
*StartLink
;
725 UINT64 CpuArchAttributes
;
728 DEBUG ((DEBUG_GCD
, " Status = %r\n", EFI_INVALID_PARAMETER
));
729 return EFI_INVALID_PARAMETER
;
733 if ((Operation
& GCD_MEMORY_SPACE_OPERATION
) != 0) {
734 CoreAcquireGcdMemoryLock ();
735 Map
= &mGcdMemorySpaceMap
;
736 } else if ((Operation
& GCD_IO_SPACE_OPERATION
) != 0) {
737 CoreAcquireGcdIoLock ();
738 Map
= &mGcdIoSpaceMap
;
744 // Search for the list of descriptors that cover the range BaseAddress to BaseAddress+Length
746 Status
= CoreSearchGcdMapEntry (BaseAddress
, Length
, &StartLink
, &EndLink
, Map
);
747 if (EFI_ERROR (Status
)) {
748 Status
= EFI_UNSUPPORTED
;
752 ASSERT (StartLink
!= NULL
&& EndLink
!= NULL
);
755 // Verify that the list of descriptors are unallocated non-existent memory.
758 while (Link
!= EndLink
->ForwardLink
) {
759 Entry
= CR (Link
, EFI_GCD_MAP_ENTRY
, Link
, EFI_GCD_MAP_SIGNATURE
);
764 case GCD_ADD_MEMORY_OPERATION
:
765 if (Entry
->GcdMemoryType
!= EfiGcdMemoryTypeNonExistent
||
766 Entry
->ImageHandle
!= NULL
) {
767 Status
= EFI_ACCESS_DENIED
;
771 case GCD_ADD_IO_OPERATION
:
772 if (Entry
->GcdIoType
!= EfiGcdIoTypeNonExistent
||
773 Entry
->ImageHandle
!= NULL
) {
774 Status
= EFI_ACCESS_DENIED
;
781 case GCD_FREE_MEMORY_OPERATION
:
782 case GCD_FREE_IO_OPERATION
:
783 if (Entry
->ImageHandle
== NULL
) {
784 Status
= EFI_NOT_FOUND
;
791 case GCD_REMOVE_MEMORY_OPERATION
:
792 if (Entry
->GcdMemoryType
== EfiGcdMemoryTypeNonExistent
) {
793 Status
= EFI_NOT_FOUND
;
796 if (Entry
->ImageHandle
!= NULL
) {
797 Status
= EFI_ACCESS_DENIED
;
801 case GCD_REMOVE_IO_OPERATION
:
802 if (Entry
->GcdIoType
== EfiGcdIoTypeNonExistent
) {
803 Status
= EFI_NOT_FOUND
;
806 if (Entry
->ImageHandle
!= NULL
) {
807 Status
= EFI_ACCESS_DENIED
;
812 // Set attributes operation
814 case GCD_SET_ATTRIBUTES_MEMORY_OPERATION
:
815 if ((Attributes
& EFI_MEMORY_RUNTIME
) != 0) {
816 if ((BaseAddress
& EFI_PAGE_MASK
) != 0 || (Length
& EFI_PAGE_MASK
) != 0) {
817 Status
= EFI_INVALID_PARAMETER
;
821 if ((Entry
->Capabilities
& Attributes
) != Attributes
) {
822 Status
= EFI_UNSUPPORTED
;
827 // Set capabilities operation
829 case GCD_SET_CAPABILITIES_MEMORY_OPERATION
:
830 if ((BaseAddress
& EFI_PAGE_MASK
) != 0 || (Length
& EFI_PAGE_MASK
) != 0) {
831 Status
= EFI_INVALID_PARAMETER
;
836 // Current attributes must still be supported with new capabilities
838 if ((Capabilities
& Entry
->Attributes
) != Entry
->Attributes
) {
839 Status
= EFI_UNSUPPORTED
;
844 Link
= Link
->ForwardLink
;
848 // Allocate work space to perform this operation
850 Status
= CoreAllocateGcdMapEntry (&TopEntry
, &BottomEntry
);
851 if (EFI_ERROR (Status
)) {
852 Status
= EFI_OUT_OF_RESOURCES
;
855 ASSERT (TopEntry
!= NULL
&& BottomEntry
!= NULL
);
857 if (Operation
== GCD_SET_ATTRIBUTES_MEMORY_OPERATION
) {
859 // Call CPU Arch Protocol to attempt to set attributes on the range
861 CpuArchAttributes
= ConverToCpuArchAttributes (Attributes
);
862 if (CpuArchAttributes
!= INVALID_CPU_ARCH_ATTRIBUTES
) {
864 Status
= EFI_NOT_AVAILABLE_YET
;
866 Status
= gCpu
->SetMemoryAttributes (
873 if (EFI_ERROR (Status
)) {
874 CoreFreePool (TopEntry
);
875 CoreFreePool (BottomEntry
);
882 // Convert/Insert the list of descriptors from StartLink to EndLink
885 while (Link
!= EndLink
->ForwardLink
) {
886 Entry
= CR (Link
, EFI_GCD_MAP_ENTRY
, Link
, EFI_GCD_MAP_SIGNATURE
);
887 CoreInsertGcdMapEntry (Link
, Entry
, BaseAddress
, Length
, TopEntry
, BottomEntry
);
892 case GCD_ADD_MEMORY_OPERATION
:
893 Entry
->GcdMemoryType
= GcdMemoryType
;
894 if (GcdMemoryType
== EfiGcdMemoryTypeMemoryMappedIo
) {
895 Entry
->Capabilities
= Capabilities
| EFI_MEMORY_RUNTIME
| EFI_MEMORY_PORT_IO
;
897 Entry
->Capabilities
= Capabilities
| EFI_MEMORY_RUNTIME
;
900 case GCD_ADD_IO_OPERATION
:
901 Entry
->GcdIoType
= GcdIoType
;
906 case GCD_FREE_MEMORY_OPERATION
:
907 case GCD_FREE_IO_OPERATION
:
908 Entry
->ImageHandle
= NULL
;
909 Entry
->DeviceHandle
= NULL
;
914 case GCD_REMOVE_MEMORY_OPERATION
:
915 Entry
->GcdMemoryType
= EfiGcdMemoryTypeNonExistent
;
916 Entry
->Capabilities
= 0;
918 case GCD_REMOVE_IO_OPERATION
:
919 Entry
->GcdIoType
= EfiGcdIoTypeNonExistent
;
922 // Set attributes operation
924 case GCD_SET_ATTRIBUTES_MEMORY_OPERATION
:
925 Entry
->Attributes
= Attributes
;
928 // Set capabilities operation
930 case GCD_SET_CAPABILITIES_MEMORY_OPERATION
:
931 Entry
->Capabilities
= Capabilities
;
934 Link
= Link
->ForwardLink
;
940 Status
= CoreCleanupGcdMapEntry (TopEntry
, BottomEntry
, StartLink
, EndLink
, Map
);
943 DEBUG ((DEBUG_GCD
, " Status = %r\n", Status
));
945 if ((Operation
& GCD_MEMORY_SPACE_OPERATION
) != 0) {
946 CoreReleaseGcdMemoryLock ();
947 CoreDumpGcdMemorySpaceMap (FALSE
);
949 if ((Operation
& GCD_IO_SPACE_OPERATION
) != 0) {
950 CoreReleaseGcdIoLock ();
951 CoreDumpGcdIoSpaceMap (FALSE
);
959 Check whether an entry could be used to allocate space.
961 @param Operation Allocate memory or IO
962 @param Entry The entry to be tested
963 @param GcdMemoryType The desired memory type
964 @param GcdIoType The desired IO type
966 @retval EFI_NOT_FOUND The memory type does not match or there's an
967 image handle on the entry.
968 @retval EFI_UNSUPPORTED The operation unsupported.
969 @retval EFI_SUCCESS It's ok for this entry to be used to allocate
974 CoreAllocateSpaceCheckEntry (
976 IN EFI_GCD_MAP_ENTRY
*Entry
,
977 IN EFI_GCD_MEMORY_TYPE GcdMemoryType
,
978 IN EFI_GCD_IO_TYPE GcdIoType
981 if (Entry
->ImageHandle
!= NULL
) {
982 return EFI_NOT_FOUND
;
985 case GCD_ALLOCATE_MEMORY_OPERATION
:
986 if (Entry
->GcdMemoryType
!= GcdMemoryType
) {
987 return EFI_NOT_FOUND
;
990 case GCD_ALLOCATE_IO_OPERATION
:
991 if (Entry
->GcdIoType
!= GcdIoType
) {
992 return EFI_NOT_FOUND
;
996 return EFI_UNSUPPORTED
;
1003 Allocate space on specified address and length.
1005 @param Operation The type of operation (memory or IO)
1006 @param GcdAllocateType The type of allocate operation
1007 @param GcdMemoryType The desired memory type
1008 @param GcdIoType The desired IO type
1009 @param Alignment Align with 2^Alignment
1010 @param Length Length to allocate
1011 @param BaseAddress Base address to allocate
1012 @param ImageHandle The image handle consume the allocated space.
1013 @param DeviceHandle The device handle consume the allocated space.
1015 @retval EFI_INVALID_PARAMETER Invalid parameter.
1016 @retval EFI_NOT_FOUND No descriptor for the desired space exists.
1017 @retval EFI_SUCCESS Space successfully allocated.
1023 IN EFI_GCD_ALLOCATE_TYPE GcdAllocateType
,
1024 IN EFI_GCD_MEMORY_TYPE GcdMemoryType
,
1025 IN EFI_GCD_IO_TYPE GcdIoType
,
1028 IN OUT EFI_PHYSICAL_ADDRESS
*BaseAddress
,
1029 IN EFI_HANDLE ImageHandle
,
1030 IN EFI_HANDLE DeviceHandle OPTIONAL
1034 EFI_PHYSICAL_ADDRESS AlignmentMask
;
1035 EFI_PHYSICAL_ADDRESS MaxAddress
;
1038 LIST_ENTRY
*SubLink
;
1039 EFI_GCD_MAP_ENTRY
*Entry
;
1040 EFI_GCD_MAP_ENTRY
*TopEntry
;
1041 EFI_GCD_MAP_ENTRY
*BottomEntry
;
1042 LIST_ENTRY
*StartLink
;
1043 LIST_ENTRY
*EndLink
;
1047 // Make sure parameters are valid
1049 if ((UINT32
)GcdAllocateType
>= EfiGcdMaxAllocateType
) {
1050 DEBUG ((DEBUG_GCD
, " Status = %r\n", EFI_INVALID_PARAMETER
));
1051 return EFI_INVALID_PARAMETER
;
1053 if ((UINT32
)GcdMemoryType
>= EfiGcdMemoryTypeMaximum
) {
1054 DEBUG ((DEBUG_GCD
, " Status = %r\n", EFI_INVALID_PARAMETER
));
1055 return EFI_INVALID_PARAMETER
;
1057 if ((UINT32
)GcdIoType
>= EfiGcdIoTypeMaximum
) {
1058 DEBUG ((DEBUG_GCD
, " Status = %r\n", EFI_INVALID_PARAMETER
));
1059 return EFI_INVALID_PARAMETER
;
1061 if (BaseAddress
== NULL
) {
1062 DEBUG ((DEBUG_GCD
, " Status = %r\n", EFI_INVALID_PARAMETER
));
1063 return EFI_INVALID_PARAMETER
;
1065 if (ImageHandle
== NULL
) {
1066 DEBUG ((DEBUG_GCD
, " Status = %r\n", EFI_INVALID_PARAMETER
));
1067 return EFI_INVALID_PARAMETER
;
1069 if (Alignment
>= 64) {
1070 DEBUG ((DEBUG_GCD
, " Status = %r\n", EFI_NOT_FOUND
));
1071 return EFI_NOT_FOUND
;
1074 DEBUG ((DEBUG_GCD
, " Status = %r\n", EFI_INVALID_PARAMETER
));
1075 return EFI_INVALID_PARAMETER
;
1079 if ((Operation
& GCD_MEMORY_SPACE_OPERATION
) != 0) {
1080 CoreAcquireGcdMemoryLock ();
1081 Map
= &mGcdMemorySpaceMap
;
1082 } else if ((Operation
& GCD_IO_SPACE_OPERATION
) != 0) {
1083 CoreAcquireGcdIoLock ();
1084 Map
= &mGcdIoSpaceMap
;
1093 // Compute alignment bit mask
1095 AlignmentMask
= LShiftU64 (1, Alignment
) - 1;
1097 if (GcdAllocateType
== EfiGcdAllocateAddress
) {
1099 // Verify that the BaseAddress passed in is aligned correctly
1101 if ((*BaseAddress
& AlignmentMask
) != 0) {
1102 Status
= EFI_NOT_FOUND
;
1107 // Search for the list of descriptors that cover the range BaseAddress to BaseAddress+Length
1109 Status
= CoreSearchGcdMapEntry (*BaseAddress
, Length
, &StartLink
, &EndLink
, Map
);
1110 if (EFI_ERROR (Status
)) {
1111 Status
= EFI_NOT_FOUND
;
1114 ASSERT (StartLink
!= NULL
&& EndLink
!= NULL
);
1117 // Verify that the list of descriptors are unallocated memory matching GcdMemoryType.
1120 while (Link
!= EndLink
->ForwardLink
) {
1121 Entry
= CR (Link
, EFI_GCD_MAP_ENTRY
, Link
, EFI_GCD_MAP_SIGNATURE
);
1122 Link
= Link
->ForwardLink
;
1123 Status
= CoreAllocateSpaceCheckEntry (Operation
, Entry
, GcdMemoryType
, GcdIoType
);
1124 if (EFI_ERROR (Status
)) {
1131 Entry
= CR (Map
->BackLink
, EFI_GCD_MAP_ENTRY
, Link
, EFI_GCD_MAP_SIGNATURE
);
1134 // Compute the maximum address to use in the search algorithm
1136 if (GcdAllocateType
== EfiGcdAllocateMaxAddressSearchBottomUp
||
1137 GcdAllocateType
== EfiGcdAllocateMaxAddressSearchTopDown
) {
1138 MaxAddress
= *BaseAddress
;
1140 MaxAddress
= Entry
->EndAddress
;
1144 // Verify that the list of descriptors are unallocated memory matching GcdMemoryType.
1146 if (GcdAllocateType
== EfiGcdAllocateMaxAddressSearchTopDown
||
1147 GcdAllocateType
== EfiGcdAllocateAnySearchTopDown
) {
1148 Link
= Map
->BackLink
;
1150 Link
= Map
->ForwardLink
;
1152 while (Link
!= Map
) {
1153 Entry
= CR (Link
, EFI_GCD_MAP_ENTRY
, Link
, EFI_GCD_MAP_SIGNATURE
);
1155 if (GcdAllocateType
== EfiGcdAllocateMaxAddressSearchTopDown
||
1156 GcdAllocateType
== EfiGcdAllocateAnySearchTopDown
) {
1157 Link
= Link
->BackLink
;
1159 Link
= Link
->ForwardLink
;
1162 Status
= CoreAllocateSpaceCheckEntry (Operation
, Entry
, GcdMemoryType
, GcdIoType
);
1163 if (EFI_ERROR (Status
)) {
1167 if (GcdAllocateType
== EfiGcdAllocateMaxAddressSearchTopDown
||
1168 GcdAllocateType
== EfiGcdAllocateAnySearchTopDown
) {
1169 if ((Entry
->BaseAddress
+ Length
) > MaxAddress
) {
1172 if (Length
> (Entry
->EndAddress
+ 1)) {
1173 Status
= EFI_NOT_FOUND
;
1176 if (Entry
->EndAddress
> MaxAddress
) {
1177 *BaseAddress
= MaxAddress
;
1179 *BaseAddress
= Entry
->EndAddress
;
1181 *BaseAddress
= (*BaseAddress
+ 1 - Length
) & (~AlignmentMask
);
1183 *BaseAddress
= (Entry
->BaseAddress
+ AlignmentMask
) & (~AlignmentMask
);
1184 if ((*BaseAddress
+ Length
- 1) > MaxAddress
) {
1185 Status
= EFI_NOT_FOUND
;
1191 // Search for the list of descriptors that cover the range BaseAddress to BaseAddress+Length
1193 Status
= CoreSearchGcdMapEntry (*BaseAddress
, Length
, &StartLink
, &EndLink
, Map
);
1194 if (EFI_ERROR (Status
)) {
1195 Status
= EFI_NOT_FOUND
;
1198 ASSERT (StartLink
!= NULL
&& EndLink
!= NULL
);
1202 // Verify that the list of descriptors are unallocated memory matching GcdMemoryType.
1205 SubLink
= StartLink
;
1206 while (SubLink
!= EndLink
->ForwardLink
) {
1207 Entry
= CR (SubLink
, EFI_GCD_MAP_ENTRY
, Link
, EFI_GCD_MAP_SIGNATURE
);
1208 Status
= CoreAllocateSpaceCheckEntry (Operation
, Entry
, GcdMemoryType
, GcdIoType
);
1209 if (EFI_ERROR (Status
)) {
1214 SubLink
= SubLink
->ForwardLink
;
1222 Status
= EFI_NOT_FOUND
;
1227 // Allocate work space to perform this operation
1229 Status
= CoreAllocateGcdMapEntry (&TopEntry
, &BottomEntry
);
1230 if (EFI_ERROR (Status
)) {
1231 Status
= EFI_OUT_OF_RESOURCES
;
1234 ASSERT (TopEntry
!= NULL
&& BottomEntry
!= NULL
);
1237 // Convert/Insert the list of descriptors from StartLink to EndLink
1240 while (Link
!= EndLink
->ForwardLink
) {
1241 Entry
= CR (Link
, EFI_GCD_MAP_ENTRY
, Link
, EFI_GCD_MAP_SIGNATURE
);
1242 CoreInsertGcdMapEntry (Link
, Entry
, *BaseAddress
, Length
, TopEntry
, BottomEntry
);
1243 Entry
->ImageHandle
= ImageHandle
;
1244 Entry
->DeviceHandle
= DeviceHandle
;
1245 Link
= Link
->ForwardLink
;
1251 Status
= CoreCleanupGcdMapEntry (TopEntry
, BottomEntry
, StartLink
, EndLink
, Map
);
1254 DEBUG ((DEBUG_GCD
, " Status = %r", Status
));
1255 if (!EFI_ERROR (Status
)) {
1256 DEBUG ((DEBUG_GCD
, " (BaseAddress = %016lx)", *BaseAddress
));
1258 DEBUG ((DEBUG_GCD
, "\n"));
1260 if ((Operation
& GCD_MEMORY_SPACE_OPERATION
) != 0) {
1261 CoreReleaseGcdMemoryLock ();
1262 CoreDumpGcdMemorySpaceMap (FALSE
);
1264 if ((Operation
& GCD_IO_SPACE_OPERATION
) !=0) {
1265 CoreReleaseGcdIoLock ();
1266 CoreDumpGcdIoSpaceMap (FALSE
);
1274 Add a segment of memory to GCD map.
1276 @param GcdMemoryType Memory type of the segment.
1277 @param BaseAddress Base address of the segment.
1278 @param Length Length of the segment.
1279 @param Capabilities alterable attributes of the segment.
1281 @retval EFI_INVALID_PARAMETER Invalid parameters.
1282 @retval EFI_SUCCESS Successfully add a segment of memory space.
1286 CoreInternalAddMemorySpace (
1287 IN EFI_GCD_MEMORY_TYPE GcdMemoryType
,
1288 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
1290 IN UINT64 Capabilities
1293 DEBUG ((DEBUG_GCD
, "GCD:AddMemorySpace(Base=%016lx,Length=%016lx)\n", BaseAddress
, Length
));
1294 DEBUG ((DEBUG_GCD
, " GcdMemoryType = %a\n", mGcdMemoryTypeNames
[MIN (GcdMemoryType
, EfiGcdMemoryTypeMaximum
)]));
1295 DEBUG ((DEBUG_GCD
, " Capabilities = %016lx\n", Capabilities
));
1298 // Make sure parameters are valid
1300 if (GcdMemoryType
<= EfiGcdMemoryTypeNonExistent
|| GcdMemoryType
>= EfiGcdMemoryTypeMaximum
) {
1301 return EFI_INVALID_PARAMETER
;
1304 return CoreConvertSpace (GCD_ADD_MEMORY_OPERATION
, GcdMemoryType
, (EFI_GCD_IO_TYPE
) 0, BaseAddress
, Length
, Capabilities
, 0);
1308 // GCD Core Services
1312 Allocates nonexistent memory, reserved memory, system memory, or memorymapped
1313 I/O resources from the global coherency domain of the processor.
1315 @param GcdAllocateType The type of allocate operation
1316 @param GcdMemoryType The desired memory type
1317 @param Alignment Align with 2^Alignment
1318 @param Length Length to allocate
1319 @param BaseAddress Base address to allocate
1320 @param ImageHandle The image handle consume the allocated space.
1321 @param DeviceHandle The device handle consume the allocated space.
1323 @retval EFI_INVALID_PARAMETER Invalid parameter.
1324 @retval EFI_NOT_FOUND No descriptor contains the desired space.
1325 @retval EFI_SUCCESS Memory space successfully allocated.
1330 CoreAllocateMemorySpace (
1331 IN EFI_GCD_ALLOCATE_TYPE GcdAllocateType
,
1332 IN EFI_GCD_MEMORY_TYPE GcdMemoryType
,
1335 IN OUT EFI_PHYSICAL_ADDRESS
*BaseAddress
,
1336 IN EFI_HANDLE ImageHandle
,
1337 IN EFI_HANDLE DeviceHandle OPTIONAL
1340 DEBUG ((DEBUG_GCD
, "GCD:AllocateMemorySpace(Base=%016lx,Length=%016lx)\n", *BaseAddress
, Length
));
1341 DEBUG ((DEBUG_GCD
, " GcdAllocateType = %a\n", mGcdAllocationTypeNames
[MIN (GcdAllocateType
, EfiGcdMaxAllocateType
)]));
1342 DEBUG ((DEBUG_GCD
, " GcdMemoryType = %a\n", mGcdMemoryTypeNames
[MIN (GcdMemoryType
, EfiGcdMemoryTypeMaximum
)]));
1343 DEBUG ((DEBUG_GCD
, " Alignment = %016lx\n", LShiftU64 (1, Alignment
)));
1344 DEBUG ((DEBUG_GCD
, " ImageHandle = %p\n", ImageHandle
));
1345 DEBUG ((DEBUG_GCD
, " DeviceHandle = %p\n", DeviceHandle
));
1347 return CoreAllocateSpace (
1348 GCD_ALLOCATE_MEMORY_OPERATION
,
1351 (EFI_GCD_IO_TYPE
) 0,
1362 Adds reserved memory, system memory, or memory-mapped I/O resources to the
1363 global coherency domain of the processor.
1365 @param GcdMemoryType Memory type of the memory space.
1366 @param BaseAddress Base address of the memory space.
1367 @param Length Length of the memory space.
1368 @param Capabilities alterable attributes of the memory space.
1370 @retval EFI_SUCCESS Merged this memory space into GCD map.
1375 CoreAddMemorySpace (
1376 IN EFI_GCD_MEMORY_TYPE GcdMemoryType
,
1377 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
1379 IN UINT64 Capabilities
1383 EFI_PHYSICAL_ADDRESS PageBaseAddress
;
1386 Status
= CoreInternalAddMemorySpace (GcdMemoryType
, BaseAddress
, Length
, Capabilities
);
1388 if (!EFI_ERROR (Status
) && ((GcdMemoryType
== EfiGcdMemoryTypeSystemMemory
) || (GcdMemoryType
== EfiGcdMemoryTypeMoreReliable
))) {
1390 PageBaseAddress
= PageAlignAddress (BaseAddress
);
1391 PageLength
= PageAlignLength (BaseAddress
+ Length
- PageBaseAddress
);
1393 Status
= CoreAllocateMemorySpace (
1394 EfiGcdAllocateAddress
,
1399 gDxeCoreImageHandle
,
1403 if (!EFI_ERROR (Status
)) {
1404 CoreAddMemoryDescriptor (
1405 EfiConventionalMemory
,
1407 RShiftU64 (PageLength
, EFI_PAGE_SHIFT
),
1411 for (; PageLength
!= 0; PageLength
-= EFI_PAGE_SIZE
, PageBaseAddress
+= EFI_PAGE_SIZE
) {
1412 Status
= CoreAllocateMemorySpace (
1413 EfiGcdAllocateAddress
,
1418 gDxeCoreImageHandle
,
1422 if (!EFI_ERROR (Status
)) {
1423 CoreAddMemoryDescriptor (
1424 EfiConventionalMemory
,
1438 Frees nonexistent memory, reserved memory, system memory, or memory-mapped
1439 I/O resources from the global coherency domain of the processor.
1441 @param BaseAddress Base address of the memory space.
1442 @param Length Length of the memory space.
1444 @retval EFI_SUCCESS Space successfully freed.
1449 CoreFreeMemorySpace (
1450 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
1454 DEBUG ((DEBUG_GCD
, "GCD:FreeMemorySpace(Base=%016lx,Length=%016lx)\n", BaseAddress
, Length
));
1456 return CoreConvertSpace (GCD_FREE_MEMORY_OPERATION
, (EFI_GCD_MEMORY_TYPE
) 0, (EFI_GCD_IO_TYPE
) 0, BaseAddress
, Length
, 0, 0);
1461 Removes reserved memory, system memory, or memory-mapped I/O resources from
1462 the global coherency domain of the processor.
1464 @param BaseAddress Base address of the memory space.
1465 @param Length Length of the memory space.
1467 @retval EFI_SUCCESS Successfully remove a segment of memory space.
1472 CoreRemoveMemorySpace (
1473 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
1477 DEBUG ((DEBUG_GCD
, "GCD:RemoveMemorySpace(Base=%016lx,Length=%016lx)\n", BaseAddress
, Length
));
1479 return CoreConvertSpace (GCD_REMOVE_MEMORY_OPERATION
, (EFI_GCD_MEMORY_TYPE
) 0, (EFI_GCD_IO_TYPE
) 0, BaseAddress
, Length
, 0, 0);
1484 Build a memory descriptor according to an entry.
1486 @param Descriptor The descriptor to be built
1487 @param Entry According to this entry
1491 BuildMemoryDescriptor (
1492 IN OUT EFI_GCD_MEMORY_SPACE_DESCRIPTOR
*Descriptor
,
1493 IN EFI_GCD_MAP_ENTRY
*Entry
1496 Descriptor
->BaseAddress
= Entry
->BaseAddress
;
1497 Descriptor
->Length
= Entry
->EndAddress
- Entry
->BaseAddress
+ 1;
1498 Descriptor
->Capabilities
= Entry
->Capabilities
;
1499 Descriptor
->Attributes
= Entry
->Attributes
;
1500 Descriptor
->GcdMemoryType
= Entry
->GcdMemoryType
;
1501 Descriptor
->ImageHandle
= Entry
->ImageHandle
;
1502 Descriptor
->DeviceHandle
= Entry
->DeviceHandle
;
1507 Retrieves the descriptor for a memory region containing a specified address.
1509 @param BaseAddress Specified start address
1510 @param Descriptor Specified length
1512 @retval EFI_INVALID_PARAMETER Invalid parameter
1513 @retval EFI_SUCCESS Successfully get memory space descriptor.
1518 CoreGetMemorySpaceDescriptor (
1519 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
1520 OUT EFI_GCD_MEMORY_SPACE_DESCRIPTOR
*Descriptor
1524 LIST_ENTRY
*StartLink
;
1525 LIST_ENTRY
*EndLink
;
1526 EFI_GCD_MAP_ENTRY
*Entry
;
1529 // Make sure parameters are valid
1531 if (Descriptor
== NULL
) {
1532 return EFI_INVALID_PARAMETER
;
1535 CoreAcquireGcdMemoryLock ();
1538 // Search for the list of descriptors that contain BaseAddress
1540 Status
= CoreSearchGcdMapEntry (BaseAddress
, 1, &StartLink
, &EndLink
, &mGcdMemorySpaceMap
);
1541 if (EFI_ERROR (Status
)) {
1542 Status
= EFI_NOT_FOUND
;
1544 ASSERT (StartLink
!= NULL
&& EndLink
!= NULL
);
1546 // Copy the contents of the found descriptor into Descriptor
1548 Entry
= CR (StartLink
, EFI_GCD_MAP_ENTRY
, Link
, EFI_GCD_MAP_SIGNATURE
);
1549 BuildMemoryDescriptor (Descriptor
, Entry
);
1552 CoreReleaseGcdMemoryLock ();
1559 Modifies the attributes for a memory region in the global coherency domain of the
1562 @param BaseAddress Specified start address
1563 @param Length Specified length
1564 @param Attributes Specified attributes
1566 @retval EFI_SUCCESS The attributes were set for the memory region.
1567 @retval EFI_INVALID_PARAMETER Length is zero.
1568 @retval EFI_UNSUPPORTED The processor does not support one or more bytes of the memory
1569 resource range specified by BaseAddress and Length.
1570 @retval EFI_UNSUPPORTED The bit mask of attributes is not support for the memory resource
1571 range specified by BaseAddress and Length.
1572 @retval EFI_ACCESS_DEFINED The attributes for the memory resource range specified by
1573 BaseAddress and Length cannot be modified.
1574 @retval EFI_OUT_OF_RESOURCES There are not enough system resources to modify the attributes of
1575 the memory resource range.
1576 @retval EFI_NOT_AVAILABLE_YET The attributes cannot be set because CPU architectural protocol is
1582 CoreSetMemorySpaceAttributes (
1583 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
1585 IN UINT64 Attributes
1588 DEBUG ((DEBUG_GCD
, "GCD:SetMemorySpaceAttributes(Base=%016lx,Length=%016lx)\n", BaseAddress
, Length
));
1589 DEBUG ((DEBUG_GCD
, " Attributes = %016lx\n", Attributes
));
1591 return CoreConvertSpace (GCD_SET_ATTRIBUTES_MEMORY_OPERATION
, (EFI_GCD_MEMORY_TYPE
) 0, (EFI_GCD_IO_TYPE
) 0, BaseAddress
, Length
, 0, Attributes
);
1596 Modifies the capabilities for a memory region in the global coherency domain of the
1599 @param BaseAddress The physical address that is the start address of a memory region.
1600 @param Length The size in bytes of the memory region.
1601 @param Capabilities The bit mask of capabilities that the memory region supports.
1603 @retval EFI_SUCCESS The capabilities were set for the memory region.
1604 @retval EFI_INVALID_PARAMETER Length is zero.
1605 @retval EFI_UNSUPPORTED The capabilities specified by Capabilities do not include the
1606 memory region attributes currently in use.
1607 @retval EFI_ACCESS_DENIED The capabilities for the memory resource range specified by
1608 BaseAddress and Length cannot be modified.
1609 @retval EFI_OUT_OF_RESOURCES There are not enough system resources to modify the capabilities
1610 of the memory resource range.
1614 CoreSetMemorySpaceCapabilities (
1615 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
1617 IN UINT64 Capabilities
1622 DEBUG ((DEBUG_GCD
, "GCD:CoreSetMemorySpaceCapabilities(Base=%016lx,Length=%016lx)\n", BaseAddress
, Length
));
1623 DEBUG ((DEBUG_GCD
, " Capabilities = %016lx\n", Capabilities
));
1625 Status
= CoreConvertSpace (GCD_SET_CAPABILITIES_MEMORY_OPERATION
, (EFI_GCD_MEMORY_TYPE
) 0, (EFI_GCD_IO_TYPE
) 0, BaseAddress
, Length
, Capabilities
, 0);
1626 if (!EFI_ERROR(Status
)) {
1627 CoreUpdateMemoryAttributes(BaseAddress
, RShiftU64(Length
, EFI_PAGE_SHIFT
), Capabilities
);
1635 Returns a map of the memory resources in the global coherency domain of the
1638 @param NumberOfDescriptors Number of descriptors.
1639 @param MemorySpaceMap Descriptor array
1641 @retval EFI_INVALID_PARAMETER Invalid parameter
1642 @retval EFI_OUT_OF_RESOURCES No enough buffer to allocate
1643 @retval EFI_SUCCESS Successfully get memory space map.
1648 CoreGetMemorySpaceMap (
1649 OUT UINTN
*NumberOfDescriptors
,
1650 OUT EFI_GCD_MEMORY_SPACE_DESCRIPTOR
**MemorySpaceMap
1655 EFI_GCD_MAP_ENTRY
*Entry
;
1656 EFI_GCD_MEMORY_SPACE_DESCRIPTOR
*Descriptor
;
1659 // Make sure parameters are valid
1661 if (NumberOfDescriptors
== NULL
) {
1662 return EFI_INVALID_PARAMETER
;
1664 if (MemorySpaceMap
== NULL
) {
1665 return EFI_INVALID_PARAMETER
;
1668 CoreAcquireGcdMemoryLock ();
1671 // Count the number of descriptors
1673 *NumberOfDescriptors
= CoreCountGcdMapEntry (&mGcdMemorySpaceMap
);
1676 // Allocate the MemorySpaceMap
1678 *MemorySpaceMap
= AllocatePool (*NumberOfDescriptors
* sizeof (EFI_GCD_MEMORY_SPACE_DESCRIPTOR
));
1679 if (*MemorySpaceMap
== NULL
) {
1680 Status
= EFI_OUT_OF_RESOURCES
;
1685 // Fill in the MemorySpaceMap
1687 Descriptor
= *MemorySpaceMap
;
1688 Link
= mGcdMemorySpaceMap
.ForwardLink
;
1689 while (Link
!= &mGcdMemorySpaceMap
) {
1690 Entry
= CR (Link
, EFI_GCD_MAP_ENTRY
, Link
, EFI_GCD_MAP_SIGNATURE
);
1691 BuildMemoryDescriptor (Descriptor
, Entry
);
1693 Link
= Link
->ForwardLink
;
1695 Status
= EFI_SUCCESS
;
1698 CoreReleaseGcdMemoryLock ();
1704 Adds reserved I/O or I/O resources to the global coherency domain of the processor.
1706 @param GcdIoType IO type of the segment.
1707 @param BaseAddress Base address of the segment.
1708 @param Length Length of the segment.
1710 @retval EFI_SUCCESS Merged this segment into GCD map.
1711 @retval EFI_INVALID_PARAMETER Parameter not valid
1717 IN EFI_GCD_IO_TYPE GcdIoType
,
1718 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
1722 DEBUG ((DEBUG_GCD
, "GCD:AddIoSpace(Base=%016lx,Length=%016lx)\n", BaseAddress
, Length
));
1723 DEBUG ((DEBUG_GCD
, " GcdIoType = %a\n", mGcdIoTypeNames
[MIN (GcdIoType
, EfiGcdIoTypeMaximum
)]));
1726 // Make sure parameters are valid
1728 if (GcdIoType
<= EfiGcdIoTypeNonExistent
|| GcdIoType
>= EfiGcdIoTypeMaximum
) {
1729 return EFI_INVALID_PARAMETER
;
1731 return CoreConvertSpace (GCD_ADD_IO_OPERATION
, (EFI_GCD_MEMORY_TYPE
) 0, GcdIoType
, BaseAddress
, Length
, 0, 0);
1736 Allocates nonexistent I/O, reserved I/O, or I/O resources from the global coherency
1737 domain of the processor.
1739 @param GcdAllocateType The type of allocate operation
1740 @param GcdIoType The desired IO type
1741 @param Alignment Align with 2^Alignment
1742 @param Length Length to allocate
1743 @param BaseAddress Base address to allocate
1744 @param ImageHandle The image handle consume the allocated space.
1745 @param DeviceHandle The device handle consume the allocated space.
1747 @retval EFI_INVALID_PARAMETER Invalid parameter.
1748 @retval EFI_NOT_FOUND No descriptor contains the desired space.
1749 @retval EFI_SUCCESS IO space successfully allocated.
1754 CoreAllocateIoSpace (
1755 IN EFI_GCD_ALLOCATE_TYPE GcdAllocateType
,
1756 IN EFI_GCD_IO_TYPE GcdIoType
,
1759 IN OUT EFI_PHYSICAL_ADDRESS
*BaseAddress
,
1760 IN EFI_HANDLE ImageHandle
,
1761 IN EFI_HANDLE DeviceHandle OPTIONAL
1764 DEBUG ((DEBUG_GCD
, "GCD:AllocateIoSpace(Base=%016lx,Length=%016lx)\n", *BaseAddress
, Length
));
1765 DEBUG ((DEBUG_GCD
, " GcdAllocateType = %a\n", mGcdAllocationTypeNames
[MIN (GcdAllocateType
, EfiGcdMaxAllocateType
)]));
1766 DEBUG ((DEBUG_GCD
, " GcdIoType = %a\n", mGcdIoTypeNames
[MIN (GcdIoType
, EfiGcdIoTypeMaximum
)]));
1767 DEBUG ((DEBUG_GCD
, " Alignment = %016lx\n", LShiftU64 (1, Alignment
)));
1768 DEBUG ((DEBUG_GCD
, " ImageHandle = %p\n", ImageHandle
));
1769 DEBUG ((DEBUG_GCD
, " DeviceHandle = %p\n", DeviceHandle
));
1771 return CoreAllocateSpace (
1772 GCD_ALLOCATE_IO_OPERATION
,
1774 (EFI_GCD_MEMORY_TYPE
) 0,
1786 Frees nonexistent I/O, reserved I/O, or I/O resources from the global coherency
1787 domain of the processor.
1789 @param BaseAddress Base address of the segment.
1790 @param Length Length of the segment.
1792 @retval EFI_SUCCESS Space successfully freed.
1798 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
1802 DEBUG ((DEBUG_GCD
, "GCD:FreeIoSpace(Base=%016lx,Length=%016lx)\n", BaseAddress
, Length
));
1804 return CoreConvertSpace (GCD_FREE_IO_OPERATION
, (EFI_GCD_MEMORY_TYPE
) 0, (EFI_GCD_IO_TYPE
) 0, BaseAddress
, Length
, 0, 0);
1809 Removes reserved I/O or I/O resources from the global coherency domain of the
1812 @param BaseAddress Base address of the segment.
1813 @param Length Length of the segment.
1815 @retval EFI_SUCCESS Successfully removed a segment of IO space.
1821 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
1825 DEBUG ((DEBUG_GCD
, "GCD:RemoveIoSpace(Base=%016lx,Length=%016lx)\n", BaseAddress
, Length
));
1827 return CoreConvertSpace (GCD_REMOVE_IO_OPERATION
, (EFI_GCD_MEMORY_TYPE
) 0, (EFI_GCD_IO_TYPE
) 0, BaseAddress
, Length
, 0, 0);
1832 Build a IO descriptor according to an entry.
1834 @param Descriptor The descriptor to be built
1835 @param Entry According to this entry
1840 IN EFI_GCD_IO_SPACE_DESCRIPTOR
*Descriptor
,
1841 IN EFI_GCD_MAP_ENTRY
*Entry
1844 Descriptor
->BaseAddress
= Entry
->BaseAddress
;
1845 Descriptor
->Length
= Entry
->EndAddress
- Entry
->BaseAddress
+ 1;
1846 Descriptor
->GcdIoType
= Entry
->GcdIoType
;
1847 Descriptor
->ImageHandle
= Entry
->ImageHandle
;
1848 Descriptor
->DeviceHandle
= Entry
->DeviceHandle
;
1853 Retrieves the descriptor for an I/O region containing a specified address.
1855 @param BaseAddress Specified start address
1856 @param Descriptor Specified length
1858 @retval EFI_INVALID_PARAMETER Descriptor is NULL.
1859 @retval EFI_SUCCESS Successfully get the IO space descriptor.
1864 CoreGetIoSpaceDescriptor (
1865 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
1866 OUT EFI_GCD_IO_SPACE_DESCRIPTOR
*Descriptor
1870 LIST_ENTRY
*StartLink
;
1871 LIST_ENTRY
*EndLink
;
1872 EFI_GCD_MAP_ENTRY
*Entry
;
1875 // Make sure parameters are valid
1877 if (Descriptor
== NULL
) {
1878 return EFI_INVALID_PARAMETER
;
1881 CoreAcquireGcdIoLock ();
1884 // Search for the list of descriptors that contain BaseAddress
1886 Status
= CoreSearchGcdMapEntry (BaseAddress
, 1, &StartLink
, &EndLink
, &mGcdIoSpaceMap
);
1887 if (EFI_ERROR (Status
)) {
1888 Status
= EFI_NOT_FOUND
;
1890 ASSERT (StartLink
!= NULL
&& EndLink
!= NULL
);
1892 // Copy the contents of the found descriptor into Descriptor
1894 Entry
= CR (StartLink
, EFI_GCD_MAP_ENTRY
, Link
, EFI_GCD_MAP_SIGNATURE
);
1895 BuildIoDescriptor (Descriptor
, Entry
);
1898 CoreReleaseGcdIoLock ();
1905 Returns a map of the I/O resources in the global coherency domain of the processor.
1907 @param NumberOfDescriptors Number of descriptors.
1908 @param IoSpaceMap Descriptor array
1910 @retval EFI_INVALID_PARAMETER Invalid parameter
1911 @retval EFI_OUT_OF_RESOURCES No enough buffer to allocate
1912 @retval EFI_SUCCESS Successfully get IO space map.
1918 OUT UINTN
*NumberOfDescriptors
,
1919 OUT EFI_GCD_IO_SPACE_DESCRIPTOR
**IoSpaceMap
1924 EFI_GCD_MAP_ENTRY
*Entry
;
1925 EFI_GCD_IO_SPACE_DESCRIPTOR
*Descriptor
;
1928 // Make sure parameters are valid
1930 if (NumberOfDescriptors
== NULL
) {
1931 return EFI_INVALID_PARAMETER
;
1933 if (IoSpaceMap
== NULL
) {
1934 return EFI_INVALID_PARAMETER
;
1937 CoreAcquireGcdIoLock ();
1940 // Count the number of descriptors
1942 *NumberOfDescriptors
= CoreCountGcdMapEntry (&mGcdIoSpaceMap
);
1945 // Allocate the IoSpaceMap
1947 *IoSpaceMap
= AllocatePool (*NumberOfDescriptors
* sizeof (EFI_GCD_IO_SPACE_DESCRIPTOR
));
1948 if (*IoSpaceMap
== NULL
) {
1949 Status
= EFI_OUT_OF_RESOURCES
;
1954 // Fill in the IoSpaceMap
1956 Descriptor
= *IoSpaceMap
;
1957 Link
= mGcdIoSpaceMap
.ForwardLink
;
1958 while (Link
!= &mGcdIoSpaceMap
) {
1959 Entry
= CR (Link
, EFI_GCD_MAP_ENTRY
, Link
, EFI_GCD_MAP_SIGNATURE
);
1960 BuildIoDescriptor (Descriptor
, Entry
);
1962 Link
= Link
->ForwardLink
;
1964 Status
= EFI_SUCCESS
;
1967 CoreReleaseGcdIoLock ();
1973 Converts a Resource Descriptor HOB attributes mask to an EFI Memory Descriptor
1976 @param GcdMemoryType Type of resource in the GCD memory map.
1977 @param Attributes The attribute mask in the Resource Descriptor
1980 @return The capabilities mask for an EFI Memory Descriptor.
1984 CoreConvertResourceDescriptorHobAttributesToCapabilities (
1985 EFI_GCD_MEMORY_TYPE GcdMemoryType
,
1989 UINT64 Capabilities
;
1990 GCD_ATTRIBUTE_CONVERSION_ENTRY
*Conversion
;
1993 // Convert the Resource HOB Attributes to an EFI Memory Capabilities mask
1995 for (Capabilities
= 0, Conversion
= mAttributeConversionTable
; Conversion
->Attribute
!= 0; Conversion
++) {
1996 if (Conversion
->Memory
|| ((GcdMemoryType
!= EfiGcdMemoryTypeSystemMemory
) && (GcdMemoryType
!= EfiGcdMemoryTypeMoreReliable
))) {
1997 if (Attributes
& Conversion
->Attribute
) {
1998 Capabilities
|= Conversion
->Capability
;
2003 return Capabilities
;
2007 Calculate total memory bin size neeeded.
2009 @return The total memory bin size neeeded.
2013 CalculateTotalMemoryBinSizeNeeded (
2021 // Loop through each memory type in the order specified by the gMemoryTypeInformation[] array
2024 for (Index
= 0; gMemoryTypeInformation
[Index
].Type
!= EfiMaxMemoryType
; Index
++) {
2025 TotalSize
+= LShiftU64 (gMemoryTypeInformation
[Index
].NumberOfPages
, EFI_PAGE_SHIFT
);
2032 External function. Initializes memory services based on the memory
2033 descriptor HOBs. This function is responsible for priming the memory
2034 map, so memory allocations and resource allocations can be made.
2035 The first part of this function can not depend on any memory services
2036 until at least one memory descriptor is provided to the memory services.
2038 @param HobStart The start address of the HOB.
2039 @param MemoryBaseAddress Start address of memory region found to init DXE
2041 @param MemoryLength Length of memory region found to init DXE core.
2043 @retval EFI_SUCCESS Memory services successfully initialized.
2047 CoreInitializeMemoryServices (
2049 OUT EFI_PHYSICAL_ADDRESS
*MemoryBaseAddress
,
2050 OUT UINT64
*MemoryLength
2053 EFI_PEI_HOB_POINTERS Hob
;
2054 EFI_MEMORY_TYPE_INFORMATION
*EfiMemoryTypeInformation
;
2057 EFI_HOB_HANDOFF_INFO_TABLE
*PhitHob
;
2058 EFI_HOB_RESOURCE_DESCRIPTOR
*ResourceHob
;
2059 EFI_HOB_RESOURCE_DESCRIPTOR
*PhitResourceHob
;
2060 EFI_PHYSICAL_ADDRESS BaseAddress
;
2063 UINT64 Capabilities
;
2064 EFI_PHYSICAL_ADDRESS TestedMemoryBaseAddress
;
2065 UINT64 TestedMemoryLength
;
2066 EFI_PHYSICAL_ADDRESS HighAddress
;
2067 EFI_HOB_GUID_TYPE
*GuidHob
;
2068 UINT32 ReservedCodePageNumber
;
2069 UINT64 MinimalMemorySizeNeeded
;
2072 // Point at the first HOB. This must be the PHIT HOB.
2074 Hob
.Raw
= *HobStart
;
2075 ASSERT (GET_HOB_TYPE (Hob
) == EFI_HOB_TYPE_HANDOFF
);
2078 // Initialize the spin locks and maps in the memory services.
2079 // Also fill in the memory services into the EFI Boot Services Table
2081 CoreInitializePool ();
2084 // Initialize Local Variables
2086 PhitResourceHob
= NULL
;
2093 // Cache the PHIT HOB for later use
2095 PhitHob
= Hob
.HandoffInformationTable
;
2097 if (PcdGet64(PcdLoadModuleAtFixAddressEnable
) != 0) {
2098 ReservedCodePageNumber
= PcdGet32(PcdLoadFixAddressRuntimeCodePageNumber
);
2099 ReservedCodePageNumber
+= PcdGet32(PcdLoadFixAddressBootTimeCodePageNumber
);
2102 // cache the Top address for loading modules at Fixed Address
2104 gLoadModuleAtFixAddressConfigurationTable
.DxeCodeTopAddress
= PhitHob
->EfiMemoryTop
2105 + EFI_PAGES_TO_SIZE(ReservedCodePageNumber
);
2108 // See if a Memory Type Information HOB is available
2110 GuidHob
= GetFirstGuidHob (&gEfiMemoryTypeInformationGuid
);
2111 if (GuidHob
!= NULL
) {
2112 EfiMemoryTypeInformation
= GET_GUID_HOB_DATA (GuidHob
);
2113 DataSize
= GET_GUID_HOB_DATA_SIZE (GuidHob
);
2114 if (EfiMemoryTypeInformation
!= NULL
&& DataSize
> 0 && DataSize
<= (EfiMaxMemoryType
+ 1) * sizeof (EFI_MEMORY_TYPE_INFORMATION
)) {
2115 CopyMem (&gMemoryTypeInformation
, EfiMemoryTypeInformation
, DataSize
);
2120 // Include the total memory bin size needed to make sure memory bin could be allocated successfully.
2122 MinimalMemorySizeNeeded
= MINIMUM_INITIAL_MEMORY_SIZE
+ CalculateTotalMemoryBinSizeNeeded ();
2125 // Find the Resource Descriptor HOB that contains PHIT range EfiFreeMemoryBottom..EfiFreeMemoryTop
2128 for (Hob
.Raw
= *HobStart
; !END_OF_HOB_LIST(Hob
); Hob
.Raw
= GET_NEXT_HOB(Hob
)) {
2130 // Skip all HOBs except Resource Descriptor HOBs
2132 if (GET_HOB_TYPE (Hob
) != EFI_HOB_TYPE_RESOURCE_DESCRIPTOR
) {
2137 // Skip Resource Descriptor HOBs that do not describe tested system memory
2139 ResourceHob
= Hob
.ResourceDescriptor
;
2140 if (ResourceHob
->ResourceType
!= EFI_RESOURCE_SYSTEM_MEMORY
) {
2143 if ((ResourceHob
->ResourceAttribute
& MEMORY_ATTRIBUTE_MASK
) != TESTED_MEMORY_ATTRIBUTES
) {
2148 // Skip Resource Descriptor HOBs that do not contain the PHIT range EfiFreeMemoryBottom..EfiFreeMemoryTop
2150 if (PhitHob
->EfiFreeMemoryBottom
< ResourceHob
->PhysicalStart
) {
2153 if (PhitHob
->EfiFreeMemoryTop
> (ResourceHob
->PhysicalStart
+ ResourceHob
->ResourceLength
)) {
2158 // Cache the resource descriptor HOB for the memory region described by the PHIT HOB
2160 PhitResourceHob
= ResourceHob
;
2164 // Compute range between PHIT EfiMemoryTop and the end of the Resource Descriptor HOB
2166 Attributes
= PhitResourceHob
->ResourceAttribute
;
2167 BaseAddress
= PageAlignAddress (PhitHob
->EfiMemoryTop
);
2168 Length
= PageAlignLength (ResourceHob
->PhysicalStart
+ ResourceHob
->ResourceLength
- BaseAddress
);
2169 if (Length
< MinimalMemorySizeNeeded
) {
2171 // If that range is not large enough to intialize the DXE Core, then
2172 // Compute range between PHIT EfiFreeMemoryBottom and PHIT EfiFreeMemoryTop
2174 BaseAddress
= PageAlignAddress (PhitHob
->EfiFreeMemoryBottom
);
2175 Length
= PageAlignLength (PhitHob
->EfiFreeMemoryTop
- BaseAddress
);
2176 if (Length
< MinimalMemorySizeNeeded
) {
2178 // If that range is not large enough to intialize the DXE Core, then
2179 // Compute range between the start of the Resource Descriptor HOB and the start of the HOB List
2181 BaseAddress
= PageAlignAddress (ResourceHob
->PhysicalStart
);
2182 Length
= PageAlignLength ((UINT64
)((UINTN
)*HobStart
- BaseAddress
));
2189 // Assert if a resource descriptor HOB for the memory region described by the PHIT was not found
2194 // Take the range in the resource descriptor HOB for the memory region described
2195 // by the PHIT as higher priority if it is big enough. It can make the memory bin
2196 // allocated to be at the same memory region with PHIT that has more better compatibility
2197 // to avoid memory fragmentation for some code practices assume and allocate <4G ACPI memory.
2199 if (Length
< MinimalMemorySizeNeeded
) {
2201 // Search all the resource descriptor HOBs from the highest possible addresses down for a memory
2202 // region that is big enough to initialize the DXE core. Always skip the PHIT Resource HOB.
2203 // The max address must be within the physically addressible range for the processor.
2205 HighAddress
= MAX_ADDRESS
;
2206 for (Hob
.Raw
= *HobStart
; !END_OF_HOB_LIST(Hob
); Hob
.Raw
= GET_NEXT_HOB(Hob
)) {
2208 // Skip the Resource Descriptor HOB that contains the PHIT
2210 if (Hob
.ResourceDescriptor
== PhitResourceHob
) {
2214 // Skip all HOBs except Resource Descriptor HOBs
2216 if (GET_HOB_TYPE (Hob
) != EFI_HOB_TYPE_RESOURCE_DESCRIPTOR
) {
2221 // Skip Resource Descriptor HOBs that do not describe tested system memory below MAX_ADDRESS
2223 ResourceHob
= Hob
.ResourceDescriptor
;
2224 if (ResourceHob
->ResourceType
!= EFI_RESOURCE_SYSTEM_MEMORY
) {
2227 if ((ResourceHob
->ResourceAttribute
& MEMORY_ATTRIBUTE_MASK
) != TESTED_MEMORY_ATTRIBUTES
) {
2230 if ((ResourceHob
->PhysicalStart
+ ResourceHob
->ResourceLength
) > (EFI_PHYSICAL_ADDRESS
)MAX_ADDRESS
) {
2235 // Skip Resource Descriptor HOBs that are below a previously found Resource Descriptor HOB
2237 if (HighAddress
!= (EFI_PHYSICAL_ADDRESS
)MAX_ADDRESS
&& ResourceHob
->PhysicalStart
<= HighAddress
) {
2242 // Skip Resource Descriptor HOBs that are not large enough to initilize the DXE Core
2244 TestedMemoryBaseAddress
= PageAlignAddress (ResourceHob
->PhysicalStart
);
2245 TestedMemoryLength
= PageAlignLength (ResourceHob
->PhysicalStart
+ ResourceHob
->ResourceLength
- TestedMemoryBaseAddress
);
2246 if (TestedMemoryLength
< MinimalMemorySizeNeeded
) {
2251 // Save the range described by the Resource Descriptor that is large enough to initilize the DXE Core
2253 BaseAddress
= TestedMemoryBaseAddress
;
2254 Length
= TestedMemoryLength
;
2255 Attributes
= ResourceHob
->ResourceAttribute
;
2256 HighAddress
= ResourceHob
->PhysicalStart
;
2260 DEBUG ((EFI_D_INFO
, "CoreInitializeMemoryServices:\n"));
2261 DEBUG ((EFI_D_INFO
, " BaseAddress - 0x%lx Length - 0x%lx MinimalMemorySizeNeeded - 0x%lx\n", BaseAddress
, Length
, MinimalMemorySizeNeeded
));
2264 // If no memory regions are found that are big enough to initialize the DXE core, then ASSERT().
2266 ASSERT (Length
>= MinimalMemorySizeNeeded
);
2269 // Convert the Resource HOB Attributes to an EFI Memory Capabilities mask
2271 if ((Attributes
& EFI_RESOURCE_ATTRIBUTE_MORE_RELIABLE
) == EFI_RESOURCE_ATTRIBUTE_MORE_RELIABLE
) {
2272 Capabilities
= CoreConvertResourceDescriptorHobAttributesToCapabilities (EfiGcdMemoryTypeMoreReliable
, Attributes
);
2274 Capabilities
= CoreConvertResourceDescriptorHobAttributesToCapabilities (EfiGcdMemoryTypeSystemMemory
, Attributes
);
2278 // Declare the very first memory region, so the EFI Memory Services are available.
2280 CoreAddMemoryDescriptor (
2281 EfiConventionalMemory
,
2283 RShiftU64 (Length
, EFI_PAGE_SHIFT
),
2287 *MemoryBaseAddress
= BaseAddress
;
2288 *MemoryLength
= Length
;
2295 External function. Initializes the GCD and memory services based on the memory
2296 descriptor HOBs. This function is responsible for priming the GCD map and the
2297 memory map, so memory allocations and resource allocations can be made. The
2298 HobStart will be relocated to a pool buffer.
2300 @param HobStart The start address of the HOB
2301 @param MemoryBaseAddress Start address of memory region found to init DXE
2303 @param MemoryLength Length of memory region found to init DXE core.
2305 @retval EFI_SUCCESS GCD services successfully initialized.
2309 CoreInitializeGcdServices (
2310 IN OUT VOID
**HobStart
,
2311 IN EFI_PHYSICAL_ADDRESS MemoryBaseAddress
,
2312 IN UINT64 MemoryLength
2315 EFI_PEI_HOB_POINTERS Hob
;
2317 EFI_HOB_HANDOFF_INFO_TABLE
*PhitHob
;
2318 UINT8 SizeOfMemorySpace
;
2319 UINT8 SizeOfIoSpace
;
2320 EFI_HOB_RESOURCE_DESCRIPTOR
*ResourceHob
;
2321 EFI_PHYSICAL_ADDRESS BaseAddress
;
2324 EFI_GCD_MAP_ENTRY
*Entry
;
2325 EFI_GCD_MEMORY_TYPE GcdMemoryType
;
2326 EFI_GCD_IO_TYPE GcdIoType
;
2327 EFI_GCD_MEMORY_SPACE_DESCRIPTOR Descriptor
;
2328 EFI_HOB_MEMORY_ALLOCATION
*MemoryHob
;
2329 EFI_HOB_FIRMWARE_VOLUME
*FirmwareVolumeHob
;
2330 UINTN NumberOfDescriptors
;
2331 EFI_GCD_MEMORY_SPACE_DESCRIPTOR
*MemorySpaceMap
;
2333 UINT64 Capabilities
;
2334 EFI_HOB_CPU
* CpuHob
;
2335 EFI_GCD_MEMORY_SPACE_DESCRIPTOR
*MemorySpaceMapHobList
;
2338 // Cache the PHIT HOB for later use
2340 PhitHob
= (EFI_HOB_HANDOFF_INFO_TABLE
*)(*HobStart
);
2343 // Get the number of address lines in the I/O and Memory space for the CPU
2345 CpuHob
= GetFirstHob (EFI_HOB_TYPE_CPU
);
2346 ASSERT (CpuHob
!= NULL
);
2347 SizeOfMemorySpace
= CpuHob
->SizeOfMemorySpace
;
2348 SizeOfIoSpace
= CpuHob
->SizeOfIoSpace
;
2351 // Initialize the GCD Memory Space Map
2353 Entry
= AllocateCopyPool (sizeof (EFI_GCD_MAP_ENTRY
), &mGcdMemorySpaceMapEntryTemplate
);
2354 ASSERT (Entry
!= NULL
);
2356 Entry
->EndAddress
= LShiftU64 (1, SizeOfMemorySpace
) - 1;
2358 InsertHeadList (&mGcdMemorySpaceMap
, &Entry
->Link
);
2360 CoreDumpGcdMemorySpaceMap (TRUE
);
2363 // Initialize the GCD I/O Space Map
2365 Entry
= AllocateCopyPool (sizeof (EFI_GCD_MAP_ENTRY
), &mGcdIoSpaceMapEntryTemplate
);
2366 ASSERT (Entry
!= NULL
);
2368 Entry
->EndAddress
= LShiftU64 (1, SizeOfIoSpace
) - 1;
2370 InsertHeadList (&mGcdIoSpaceMap
, &Entry
->Link
);
2372 CoreDumpGcdIoSpaceMap (TRUE
);
2375 // Walk the HOB list and add all resource descriptors to the GCD
2377 for (Hob
.Raw
= *HobStart
; !END_OF_HOB_LIST(Hob
); Hob
.Raw
= GET_NEXT_HOB(Hob
)) {
2379 GcdMemoryType
= EfiGcdMemoryTypeNonExistent
;
2380 GcdIoType
= EfiGcdIoTypeNonExistent
;
2382 if (GET_HOB_TYPE (Hob
) == EFI_HOB_TYPE_RESOURCE_DESCRIPTOR
) {
2384 ResourceHob
= Hob
.ResourceDescriptor
;
2386 switch (ResourceHob
->ResourceType
) {
2387 case EFI_RESOURCE_SYSTEM_MEMORY
:
2388 if ((ResourceHob
->ResourceAttribute
& MEMORY_ATTRIBUTE_MASK
) == TESTED_MEMORY_ATTRIBUTES
) {
2389 if ((ResourceHob
->ResourceAttribute
& EFI_RESOURCE_ATTRIBUTE_MORE_RELIABLE
) == EFI_RESOURCE_ATTRIBUTE_MORE_RELIABLE
) {
2390 GcdMemoryType
= EfiGcdMemoryTypeMoreReliable
;
2392 GcdMemoryType
= EfiGcdMemoryTypeSystemMemory
;
2395 if ((ResourceHob
->ResourceAttribute
& MEMORY_ATTRIBUTE_MASK
) == INITIALIZED_MEMORY_ATTRIBUTES
) {
2396 GcdMemoryType
= EfiGcdMemoryTypeReserved
;
2398 if ((ResourceHob
->ResourceAttribute
& MEMORY_ATTRIBUTE_MASK
) == PRESENT_MEMORY_ATTRIBUTES
) {
2399 GcdMemoryType
= EfiGcdMemoryTypeReserved
;
2401 if ((ResourceHob
->ResourceAttribute
& EFI_RESOURCE_ATTRIBUTE_PERSISTENT
) == EFI_RESOURCE_ATTRIBUTE_PERSISTENT
) {
2402 GcdMemoryType
= EfiGcdMemoryTypePersistentMemory
;
2405 case EFI_RESOURCE_MEMORY_MAPPED_IO
:
2406 case EFI_RESOURCE_FIRMWARE_DEVICE
:
2407 GcdMemoryType
= EfiGcdMemoryTypeMemoryMappedIo
;
2409 case EFI_RESOURCE_MEMORY_MAPPED_IO_PORT
:
2410 case EFI_RESOURCE_MEMORY_RESERVED
:
2411 GcdMemoryType
= EfiGcdMemoryTypeReserved
;
2413 case EFI_RESOURCE_IO
:
2414 GcdIoType
= EfiGcdIoTypeIo
;
2416 case EFI_RESOURCE_IO_RESERVED
:
2417 GcdIoType
= EfiGcdIoTypeReserved
;
2421 if (GcdMemoryType
!= EfiGcdMemoryTypeNonExistent
) {
2423 // Validate the Resource HOB Attributes
2425 CoreValidateResourceDescriptorHobAttributes (ResourceHob
->ResourceAttribute
);
2428 // Convert the Resource HOB Attributes to an EFI Memory Capabilities mask
2430 Capabilities
= CoreConvertResourceDescriptorHobAttributesToCapabilities (
2432 ResourceHob
->ResourceAttribute
2435 Status
= CoreInternalAddMemorySpace (
2437 ResourceHob
->PhysicalStart
,
2438 ResourceHob
->ResourceLength
,
2443 if (GcdIoType
!= EfiGcdIoTypeNonExistent
) {
2444 Status
= CoreAddIoSpace (
2446 ResourceHob
->PhysicalStart
,
2447 ResourceHob
->ResourceLength
2454 // Allocate first memory region from the GCD by the DXE core
2456 Status
= CoreGetMemorySpaceDescriptor (MemoryBaseAddress
, &Descriptor
);
2457 if (!EFI_ERROR (Status
)) {
2458 ASSERT ((Descriptor
.GcdMemoryType
== EfiGcdMemoryTypeSystemMemory
) ||
2459 (Descriptor
.GcdMemoryType
== EfiGcdMemoryTypeMoreReliable
));
2460 Status
= CoreAllocateMemorySpace (
2461 EfiGcdAllocateAddress
,
2462 Descriptor
.GcdMemoryType
,
2466 gDxeCoreImageHandle
,
2472 // Walk the HOB list and allocate all memory space that is consumed by memory allocation HOBs,
2473 // and Firmware Volume HOBs. Also update the EFI Memory Map with the memory allocation HOBs.
2475 for (Hob
.Raw
= *HobStart
; !END_OF_HOB_LIST(Hob
); Hob
.Raw
= GET_NEXT_HOB(Hob
)) {
2476 if (GET_HOB_TYPE (Hob
) == EFI_HOB_TYPE_MEMORY_ALLOCATION
) {
2477 MemoryHob
= Hob
.MemoryAllocation
;
2478 BaseAddress
= MemoryHob
->AllocDescriptor
.MemoryBaseAddress
;
2479 Status
= CoreGetMemorySpaceDescriptor (BaseAddress
, &Descriptor
);
2480 if (!EFI_ERROR (Status
)) {
2481 Status
= CoreAllocateMemorySpace (
2482 EfiGcdAllocateAddress
,
2483 Descriptor
.GcdMemoryType
,
2485 MemoryHob
->AllocDescriptor
.MemoryLength
,
2487 gDxeCoreImageHandle
,
2490 if (!EFI_ERROR (Status
) &&
2491 ((Descriptor
.GcdMemoryType
== EfiGcdMemoryTypeSystemMemory
) ||
2492 (Descriptor
.GcdMemoryType
== EfiGcdMemoryTypeMoreReliable
))) {
2493 CoreAddMemoryDescriptor (
2494 MemoryHob
->AllocDescriptor
.MemoryType
,
2495 MemoryHob
->AllocDescriptor
.MemoryBaseAddress
,
2496 RShiftU64 (MemoryHob
->AllocDescriptor
.MemoryLength
, EFI_PAGE_SHIFT
),
2497 Descriptor
.Capabilities
& (~EFI_MEMORY_RUNTIME
)
2503 if (GET_HOB_TYPE (Hob
) == EFI_HOB_TYPE_FV
) {
2504 FirmwareVolumeHob
= Hob
.FirmwareVolume
;
2505 BaseAddress
= FirmwareVolumeHob
->BaseAddress
;
2506 Status
= CoreAllocateMemorySpace (
2507 EfiGcdAllocateAddress
,
2508 EfiGcdMemoryTypeMemoryMappedIo
,
2510 FirmwareVolumeHob
->Length
,
2512 gDxeCoreImageHandle
,
2519 // Add and allocate the remaining unallocated system memory to the memory services.
2521 Status
= CoreGetMemorySpaceMap (&NumberOfDescriptors
, &MemorySpaceMap
);
2522 ASSERT (Status
== EFI_SUCCESS
);
2524 MemorySpaceMapHobList
= NULL
;
2525 for (Index
= 0; Index
< NumberOfDescriptors
; Index
++) {
2526 if ((MemorySpaceMap
[Index
].GcdMemoryType
== EfiGcdMemoryTypeSystemMemory
) ||
2527 (MemorySpaceMap
[Index
].GcdMemoryType
== EfiGcdMemoryTypeMoreReliable
)) {
2528 if (MemorySpaceMap
[Index
].ImageHandle
== NULL
) {
2529 BaseAddress
= PageAlignAddress (MemorySpaceMap
[Index
].BaseAddress
);
2530 Length
= PageAlignLength (MemorySpaceMap
[Index
].BaseAddress
+ MemorySpaceMap
[Index
].Length
- BaseAddress
);
2531 if (Length
== 0 || MemorySpaceMap
[Index
].BaseAddress
+ MemorySpaceMap
[Index
].Length
< BaseAddress
) {
2534 if (((UINTN
) MemorySpaceMap
[Index
].BaseAddress
<= (UINTN
) (*HobStart
)) &&
2535 ((UINTN
) (MemorySpaceMap
[Index
].BaseAddress
+ MemorySpaceMap
[Index
].Length
) >= (UINTN
) PhitHob
->EfiFreeMemoryBottom
)) {
2537 // Skip the memory space that covers HOB List, it should be processed
2538 // after HOB List relocation to avoid the resources allocated by others
2539 // to corrupt HOB List before its relocation.
2541 MemorySpaceMapHobList
= &MemorySpaceMap
[Index
];
2544 CoreAddMemoryDescriptor (
2545 EfiConventionalMemory
,
2547 RShiftU64 (Length
, EFI_PAGE_SHIFT
),
2548 MemorySpaceMap
[Index
].Capabilities
& (~EFI_MEMORY_RUNTIME
)
2550 Status
= CoreAllocateMemorySpace (
2551 EfiGcdAllocateAddress
,
2552 MemorySpaceMap
[Index
].GcdMemoryType
,
2556 gDxeCoreImageHandle
,
2564 // Relocate HOB List to an allocated pool buffer.
2565 // The relocation should be at after all the tested memory resources added
2566 // (except the memory space that covers HOB List) to the memory services,
2567 // because the memory resource found in CoreInitializeMemoryServices()
2568 // may have not enough remaining resource for HOB List.
2570 NewHobList
= AllocateCopyPool (
2571 (UINTN
) PhitHob
->EfiFreeMemoryBottom
- (UINTN
) (*HobStart
),
2574 ASSERT (NewHobList
!= NULL
);
2576 *HobStart
= NewHobList
;
2577 gHobList
= NewHobList
;
2579 if (MemorySpaceMapHobList
!= NULL
) {
2581 // Add and allocate the memory space that covers HOB List to the memory services
2582 // after HOB List relocation.
2584 BaseAddress
= PageAlignAddress (MemorySpaceMapHobList
->BaseAddress
);
2585 Length
= PageAlignLength (MemorySpaceMapHobList
->BaseAddress
+ MemorySpaceMapHobList
->Length
- BaseAddress
);
2586 CoreAddMemoryDescriptor (
2587 EfiConventionalMemory
,
2589 RShiftU64 (Length
, EFI_PAGE_SHIFT
),
2590 MemorySpaceMapHobList
->Capabilities
& (~EFI_MEMORY_RUNTIME
)
2592 Status
= CoreAllocateMemorySpace (
2593 EfiGcdAllocateAddress
,
2594 MemorySpaceMapHobList
->GcdMemoryType
,
2598 gDxeCoreImageHandle
,
2603 CoreFreePool (MemorySpaceMap
);