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 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.
19 #include "Mem/HeapGuard.h"
21 #define MINIMUM_INITIAL_MEMORY_SIZE 0x10000
23 #define MEMORY_ATTRIBUTE_MASK (EFI_RESOURCE_ATTRIBUTE_PRESENT | \
24 EFI_RESOURCE_ATTRIBUTE_INITIALIZED | \
25 EFI_RESOURCE_ATTRIBUTE_TESTED | \
26 EFI_RESOURCE_ATTRIBUTE_READ_PROTECTED | \
27 EFI_RESOURCE_ATTRIBUTE_WRITE_PROTECTED | \
28 EFI_RESOURCE_ATTRIBUTE_EXECUTION_PROTECTED | \
29 EFI_RESOURCE_ATTRIBUTE_READ_ONLY_PROTECTED | \
30 EFI_RESOURCE_ATTRIBUTE_16_BIT_IO | \
31 EFI_RESOURCE_ATTRIBUTE_32_BIT_IO | \
32 EFI_RESOURCE_ATTRIBUTE_64_BIT_IO | \
33 EFI_RESOURCE_ATTRIBUTE_PERSISTENT )
35 #define TESTED_MEMORY_ATTRIBUTES (EFI_RESOURCE_ATTRIBUTE_PRESENT | \
36 EFI_RESOURCE_ATTRIBUTE_INITIALIZED | \
37 EFI_RESOURCE_ATTRIBUTE_TESTED )
39 #define INITIALIZED_MEMORY_ATTRIBUTES (EFI_RESOURCE_ATTRIBUTE_PRESENT | \
40 EFI_RESOURCE_ATTRIBUTE_INITIALIZED )
42 #define PRESENT_MEMORY_ATTRIBUTES (EFI_RESOURCE_ATTRIBUTE_PRESENT)
44 #define EXCLUSIVE_MEMORY_ATTRIBUTES (EFI_MEMORY_UC | EFI_MEMORY_WC | \
45 EFI_MEMORY_WT | EFI_MEMORY_WB | \
46 EFI_MEMORY_WP | EFI_MEMORY_UCE)
48 #define NONEXCLUSIVE_MEMORY_ATTRIBUTES (EFI_MEMORY_XP | EFI_MEMORY_RP | \
54 EFI_LOCK mGcdMemorySpaceLock
= EFI_INITIALIZE_LOCK_VARIABLE (TPL_NOTIFY
);
55 EFI_LOCK mGcdIoSpaceLock
= EFI_INITIALIZE_LOCK_VARIABLE (TPL_NOTIFY
);
56 LIST_ENTRY mGcdMemorySpaceMap
= INITIALIZE_LIST_HEAD_VARIABLE (mGcdMemorySpaceMap
);
57 LIST_ENTRY mGcdIoSpaceMap
= INITIALIZE_LIST_HEAD_VARIABLE (mGcdIoSpaceMap
);
59 EFI_GCD_MAP_ENTRY mGcdMemorySpaceMapEntryTemplate
= {
60 EFI_GCD_MAP_SIGNATURE
,
69 EfiGcdMemoryTypeNonExistent
,
75 EFI_GCD_MAP_ENTRY mGcdIoSpaceMapEntryTemplate
= {
76 EFI_GCD_MAP_SIGNATURE
,
85 (EFI_GCD_MEMORY_TYPE
) 0,
86 EfiGcdIoTypeNonExistent
,
91 GCD_ATTRIBUTE_CONVERSION_ENTRY mAttributeConversionTable
[] = {
92 { EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE
, EFI_MEMORY_UC
, TRUE
},
93 { EFI_RESOURCE_ATTRIBUTE_UNCACHED_EXPORTED
, EFI_MEMORY_UCE
, TRUE
},
94 { EFI_RESOURCE_ATTRIBUTE_WRITE_COMBINEABLE
, EFI_MEMORY_WC
, TRUE
},
95 { EFI_RESOURCE_ATTRIBUTE_WRITE_THROUGH_CACHEABLE
, EFI_MEMORY_WT
, TRUE
},
96 { EFI_RESOURCE_ATTRIBUTE_WRITE_BACK_CACHEABLE
, EFI_MEMORY_WB
, TRUE
},
97 { EFI_RESOURCE_ATTRIBUTE_READ_PROTECTABLE
, EFI_MEMORY_RP
, TRUE
},
98 { EFI_RESOURCE_ATTRIBUTE_WRITE_PROTECTABLE
, EFI_MEMORY_WP
, TRUE
},
99 { EFI_RESOURCE_ATTRIBUTE_EXECUTION_PROTECTABLE
, EFI_MEMORY_XP
, TRUE
},
100 { EFI_RESOURCE_ATTRIBUTE_READ_ONLY_PROTECTABLE
, EFI_MEMORY_RO
, TRUE
},
101 { EFI_RESOURCE_ATTRIBUTE_PRESENT
, EFI_MEMORY_PRESENT
, FALSE
},
102 { EFI_RESOURCE_ATTRIBUTE_INITIALIZED
, EFI_MEMORY_INITIALIZED
, FALSE
},
103 { EFI_RESOURCE_ATTRIBUTE_TESTED
, EFI_MEMORY_TESTED
, FALSE
},
104 { EFI_RESOURCE_ATTRIBUTE_PERSISTABLE
, EFI_MEMORY_NV
, TRUE
},
105 { EFI_RESOURCE_ATTRIBUTE_MORE_RELIABLE
, EFI_MEMORY_MORE_RELIABLE
, TRUE
},
110 /// Lookup table used to print GCD Memory Space Map
112 GLOBAL_REMOVE_IF_UNREFERENCED CONST CHAR8
*mGcdMemoryTypeNames
[] = {
113 "NonExist ", // EfiGcdMemoryTypeNonExistent
114 "Reserved ", // EfiGcdMemoryTypeReserved
115 "SystemMem", // EfiGcdMemoryTypeSystemMemory
116 "MMIO ", // EfiGcdMemoryTypeMemoryMappedIo
117 "PersisMem", // EfiGcdMemoryTypePersistent
118 "MoreRelia", // EfiGcdMemoryTypeMoreReliable
119 "Unknown " // EfiGcdMemoryTypeMaximum
123 /// Lookup table used to print GCD I/O Space Map
125 GLOBAL_REMOVE_IF_UNREFERENCED CONST CHAR8
*mGcdIoTypeNames
[] = {
126 "NonExist", // EfiGcdIoTypeNonExistent
127 "Reserved", // EfiGcdIoTypeReserved
128 "I/O ", // EfiGcdIoTypeIo
129 "Unknown " // EfiGcdIoTypeMaximum
133 /// Lookup table used to print GCD Allocation Types
135 GLOBAL_REMOVE_IF_UNREFERENCED CONST CHAR8
*mGcdAllocationTypeNames
[] = {
136 "AnySearchBottomUp ", // EfiGcdAllocateAnySearchBottomUp
137 "MaxAddressSearchBottomUp ", // EfiGcdAllocateMaxAddressSearchBottomUp
138 "AtAddress ", // EfiGcdAllocateAddress
139 "AnySearchTopDown ", // EfiGcdAllocateAnySearchTopDown
140 "MaxAddressSearchTopDown ", // EfiGcdAllocateMaxAddressSearchTopDown
141 "Unknown " // EfiGcdMaxAllocateType
145 Dump the entire contents if the GCD Memory Space Map using DEBUG() macros when
146 PcdDebugPrintErrorLevel has the DEBUG_GCD bit set.
148 @param InitialMap TRUE if the initial GCD Memory Map is being dumped. Otherwise, FALSE.
153 CoreDumpGcdMemorySpaceMap (
159 UINTN NumberOfDescriptors
;
160 EFI_GCD_MEMORY_SPACE_DESCRIPTOR
*MemorySpaceMap
;
163 Status
= CoreGetMemorySpaceMap (&NumberOfDescriptors
, &MemorySpaceMap
);
164 ASSERT (Status
== EFI_SUCCESS
&& MemorySpaceMap
!= NULL
);
167 DEBUG ((DEBUG_GCD
, "GCD:Initial GCD Memory Space Map\n"));
169 DEBUG ((DEBUG_GCD
, "GCDMemType Range Capabilities Attributes \n"));
170 DEBUG ((DEBUG_GCD
, "========== ================================= ================ ================\n"));
171 for (Index
= 0; Index
< NumberOfDescriptors
; Index
++) {
172 DEBUG ((DEBUG_GCD
, "%a %016lx-%016lx %016lx %016lx%c\n",
173 mGcdMemoryTypeNames
[MIN (MemorySpaceMap
[Index
].GcdMemoryType
, EfiGcdMemoryTypeMaximum
)],
174 MemorySpaceMap
[Index
].BaseAddress
,
175 MemorySpaceMap
[Index
].BaseAddress
+ MemorySpaceMap
[Index
].Length
- 1,
176 MemorySpaceMap
[Index
].Capabilities
,
177 MemorySpaceMap
[Index
].Attributes
,
178 MemorySpaceMap
[Index
].ImageHandle
== NULL
? ' ' : '*'
181 DEBUG ((DEBUG_GCD
, "\n"));
182 FreePool (MemorySpaceMap
);
187 Dump the entire contents if the GCD I/O Space Map using DEBUG() macros when
188 PcdDebugPrintErrorLevel has the DEBUG_GCD bit set.
190 @param InitialMap TRUE if the initial GCD I/O Map is being dumped. Otherwise, FALSE.
195 CoreDumpGcdIoSpaceMap (
201 UINTN NumberOfDescriptors
;
202 EFI_GCD_IO_SPACE_DESCRIPTOR
*IoSpaceMap
;
205 Status
= CoreGetIoSpaceMap (&NumberOfDescriptors
, &IoSpaceMap
);
206 ASSERT (Status
== EFI_SUCCESS
&& IoSpaceMap
!= NULL
);
209 DEBUG ((DEBUG_GCD
, "GCD:Initial GCD I/O Space Map\n"));
212 DEBUG ((DEBUG_GCD
, "GCDIoType Range \n"));
213 DEBUG ((DEBUG_GCD
, "========== =================================\n"));
214 for (Index
= 0; Index
< NumberOfDescriptors
; Index
++) {
215 DEBUG ((DEBUG_GCD
, "%a %016lx-%016lx%c\n",
216 mGcdIoTypeNames
[MIN (IoSpaceMap
[Index
].GcdIoType
, EfiGcdIoTypeMaximum
)],
217 IoSpaceMap
[Index
].BaseAddress
,
218 IoSpaceMap
[Index
].BaseAddress
+ IoSpaceMap
[Index
].Length
- 1,
219 IoSpaceMap
[Index
].ImageHandle
== NULL
? ' ' : '*'
222 DEBUG ((DEBUG_GCD
, "\n"));
223 FreePool (IoSpaceMap
);
228 Validate resource descriptor HOB's attributes.
230 If Attributes includes some memory resource's settings, it should include
231 the corresponding capabilites also.
233 @param Attributes Resource descriptor HOB attributes.
237 CoreValidateResourceDescriptorHobAttributes (
241 ASSERT (((Attributes
& EFI_RESOURCE_ATTRIBUTE_READ_PROTECTED
) == 0) ||
242 ((Attributes
& EFI_RESOURCE_ATTRIBUTE_READ_PROTECTABLE
) != 0));
243 ASSERT (((Attributes
& EFI_RESOURCE_ATTRIBUTE_WRITE_PROTECTED
) == 0) ||
244 ((Attributes
& EFI_RESOURCE_ATTRIBUTE_WRITE_PROTECTABLE
) != 0));
245 ASSERT (((Attributes
& EFI_RESOURCE_ATTRIBUTE_EXECUTION_PROTECTED
) == 0) ||
246 ((Attributes
& EFI_RESOURCE_ATTRIBUTE_EXECUTION_PROTECTABLE
) != 0));
247 ASSERT (((Attributes
& EFI_RESOURCE_ATTRIBUTE_READ_ONLY_PROTECTED
) == 0) ||
248 ((Attributes
& EFI_RESOURCE_ATTRIBUTE_READ_ONLY_PROTECTABLE
) != 0));
249 ASSERT (((Attributes
& EFI_RESOURCE_ATTRIBUTE_PERSISTENT
) == 0) ||
250 ((Attributes
& EFI_RESOURCE_ATTRIBUTE_PERSISTABLE
) != 0));
254 Acquire memory lock on mGcdMemorySpaceLock.
258 CoreAcquireGcdMemoryLock (
262 CoreAcquireLock (&mGcdMemorySpaceLock
);
268 Release memory lock on mGcdMemorySpaceLock.
272 CoreReleaseGcdMemoryLock (
276 CoreReleaseLock (&mGcdMemorySpaceLock
);
282 Acquire memory lock on mGcdIoSpaceLock.
286 CoreAcquireGcdIoLock (
290 CoreAcquireLock (&mGcdIoSpaceLock
);
295 Release memory lock on mGcdIoSpaceLock.
299 CoreReleaseGcdIoLock (
303 CoreReleaseLock (&mGcdIoSpaceLock
);
309 // GCD Initialization Worker Functions
312 Aligns a value to the specified boundary.
314 @param Value 64 bit value to align
315 @param Alignment Log base 2 of the boundary to align Value to
316 @param RoundUp TRUE if Value is to be rounded up to the nearest
317 aligned boundary. FALSE is Value is to be
318 rounded down to the nearest aligned boundary.
320 @return A 64 bit value is the aligned to the value nearest Value with an alignment by Alignment.
330 UINT64 AlignmentMask
;
332 AlignmentMask
= LShiftU64 (1, Alignment
) - 1;
334 Value
+= AlignmentMask
;
336 return Value
& (~AlignmentMask
);
341 Aligns address to the page boundary.
343 @param Value 64 bit address to align
345 @return A 64 bit value is the aligned to the value nearest Value with an alignment by Alignment.
353 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
;
418 Internal function. Inserts a new descriptor into a sorted list
420 @param Link The linked list to insert the range BaseAddress
422 @param Entry A pointer to the entry that is inserted
423 @param BaseAddress The base address of the new range
424 @param Length The length of the new range in bytes
425 @param TopEntry Top pad entry to insert if needed.
426 @param BottomEntry Bottom pad entry to insert if needed.
428 @retval EFI_SUCCESS The new range was inserted into the linked list
432 CoreInsertGcdMapEntry (
434 IN EFI_GCD_MAP_ENTRY
*Entry
,
435 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
437 IN EFI_GCD_MAP_ENTRY
*TopEntry
,
438 IN EFI_GCD_MAP_ENTRY
*BottomEntry
441 ASSERT (Length
!= 0);
443 if (BaseAddress
> Entry
->BaseAddress
) {
444 ASSERT (BottomEntry
->Signature
== 0);
446 CopyMem (BottomEntry
, Entry
, sizeof (EFI_GCD_MAP_ENTRY
));
447 Entry
->BaseAddress
= BaseAddress
;
448 BottomEntry
->EndAddress
= BaseAddress
- 1;
449 InsertTailList (Link
, &BottomEntry
->Link
);
452 if ((BaseAddress
+ Length
- 1) < Entry
->EndAddress
) {
453 ASSERT (TopEntry
->Signature
== 0);
455 CopyMem (TopEntry
, Entry
, sizeof (EFI_GCD_MAP_ENTRY
));
456 TopEntry
->BaseAddress
= BaseAddress
+ Length
;
457 Entry
->EndAddress
= BaseAddress
+ Length
- 1;
458 InsertHeadList (Link
, &TopEntry
->Link
);
466 Merge the Gcd region specified by Link and its adjacent entry.
468 @param Link Specify the entry to be merged (with its
470 @param Forward Direction (forward or backward).
473 @retval EFI_SUCCESS Successfully returned.
474 @retval EFI_UNSUPPORTED These adjacent regions could not merge.
478 CoreMergeGcdMapEntry (
484 LIST_ENTRY
*AdjacentLink
;
485 EFI_GCD_MAP_ENTRY
*Entry
;
486 EFI_GCD_MAP_ENTRY
*AdjacentEntry
;
489 // Get adjacent entry
492 AdjacentLink
= Link
->ForwardLink
;
494 AdjacentLink
= Link
->BackLink
;
498 // If AdjacentLink is the head of the list, then no merge can be performed
500 if (AdjacentLink
== Map
) {
504 Entry
= CR (Link
, EFI_GCD_MAP_ENTRY
, Link
, EFI_GCD_MAP_SIGNATURE
);
505 AdjacentEntry
= CR (AdjacentLink
, EFI_GCD_MAP_ENTRY
, Link
, EFI_GCD_MAP_SIGNATURE
);
507 if (Entry
->Capabilities
!= AdjacentEntry
->Capabilities
) {
508 return EFI_UNSUPPORTED
;
510 if (Entry
->Attributes
!= AdjacentEntry
->Attributes
) {
511 return EFI_UNSUPPORTED
;
513 if (Entry
->GcdMemoryType
!= AdjacentEntry
->GcdMemoryType
) {
514 return EFI_UNSUPPORTED
;
516 if (Entry
->GcdIoType
!= AdjacentEntry
->GcdIoType
) {
517 return EFI_UNSUPPORTED
;
519 if (Entry
->ImageHandle
!= AdjacentEntry
->ImageHandle
) {
520 return EFI_UNSUPPORTED
;
522 if (Entry
->DeviceHandle
!= AdjacentEntry
->DeviceHandle
) {
523 return EFI_UNSUPPORTED
;
527 Entry
->EndAddress
= AdjacentEntry
->EndAddress
;
529 Entry
->BaseAddress
= AdjacentEntry
->BaseAddress
;
531 RemoveEntryList (AdjacentLink
);
532 CoreFreePool (AdjacentEntry
);
539 Merge adjacent entries on total chain.
541 @param TopEntry Top entry of GCD map.
542 @param BottomEntry Bottom entry of GCD map.
543 @param StartLink Start link of the list for this loop.
544 @param EndLink End link of the list for this loop.
547 @retval EFI_SUCCESS GCD map successfully cleaned up.
551 CoreCleanupGcdMapEntry (
552 IN EFI_GCD_MAP_ENTRY
*TopEntry
,
553 IN EFI_GCD_MAP_ENTRY
*BottomEntry
,
554 IN LIST_ENTRY
*StartLink
,
555 IN LIST_ENTRY
*EndLink
,
561 if (TopEntry
->Signature
== 0) {
562 CoreFreePool (TopEntry
);
564 if (BottomEntry
->Signature
== 0) {
565 CoreFreePool (BottomEntry
);
569 while (Link
!= EndLink
->ForwardLink
) {
570 CoreMergeGcdMapEntry (Link
, FALSE
, Map
);
571 Link
= Link
->ForwardLink
;
573 CoreMergeGcdMapEntry (EndLink
, TRUE
, Map
);
580 Search a segment of memory space in GCD map. The result is a range of GCD entry list.
582 @param BaseAddress The start address of the segment.
583 @param Length The length of the segment.
584 @param StartLink The first GCD entry involves this segment of
586 @param EndLink The first GCD entry involves this segment of
588 @param Map Points to the start entry to search.
590 @retval EFI_SUCCESS Successfully found the entry.
591 @retval EFI_NOT_FOUND Not found.
595 CoreSearchGcdMapEntry (
596 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
598 OUT LIST_ENTRY
**StartLink
,
599 OUT LIST_ENTRY
**EndLink
,
604 EFI_GCD_MAP_ENTRY
*Entry
;
606 ASSERT (Length
!= 0);
611 Link
= Map
->ForwardLink
;
612 while (Link
!= Map
) {
613 Entry
= CR (Link
, EFI_GCD_MAP_ENTRY
, Link
, EFI_GCD_MAP_SIGNATURE
);
614 if (BaseAddress
>= Entry
->BaseAddress
&& BaseAddress
<= Entry
->EndAddress
) {
617 if (*StartLink
!= NULL
) {
618 if ((BaseAddress
+ Length
- 1) >= Entry
->BaseAddress
&&
619 (BaseAddress
+ Length
- 1) <= Entry
->EndAddress
) {
624 Link
= Link
->ForwardLink
;
627 return EFI_NOT_FOUND
;
632 Count the amount of GCD map entries.
634 @param Map Points to the start entry to do the count loop.
640 CoreCountGcdMapEntry (
648 Link
= Map
->ForwardLink
;
649 while (Link
!= Map
) {
651 Link
= Link
->ForwardLink
;
660 Return the memory attribute specified by Attributes
662 @param Attributes A num with some attribute bits on.
664 @return The enum value of memory attribute.
668 ConverToCpuArchAttributes (
672 UINT64 CpuArchAttributes
;
674 CpuArchAttributes
= Attributes
& NONEXCLUSIVE_MEMORY_ATTRIBUTES
;
676 if ( (Attributes
& EFI_MEMORY_UC
) == EFI_MEMORY_UC
) {
677 CpuArchAttributes
|= EFI_MEMORY_UC
;
678 } else if ( (Attributes
& EFI_MEMORY_WC
) == EFI_MEMORY_WC
) {
679 CpuArchAttributes
|= EFI_MEMORY_WC
;
680 } else if ( (Attributes
& EFI_MEMORY_WT
) == EFI_MEMORY_WT
) {
681 CpuArchAttributes
|= EFI_MEMORY_WT
;
682 } else if ( (Attributes
& EFI_MEMORY_WB
) == EFI_MEMORY_WB
) {
683 CpuArchAttributes
|= EFI_MEMORY_WB
;
684 } else if ( (Attributes
& EFI_MEMORY_UCE
) == EFI_MEMORY_UCE
) {
685 CpuArchAttributes
|= EFI_MEMORY_UCE
;
686 } else if ( (Attributes
& EFI_MEMORY_WP
) == EFI_MEMORY_WP
) {
687 CpuArchAttributes
|= EFI_MEMORY_WP
;
690 return CpuArchAttributes
;
695 Do operation on a segment of memory space specified (add, free, remove, change attribute ...).
697 @param Operation The type of the operation
698 @param GcdMemoryType Additional information for the operation
699 @param GcdIoType Additional information for the operation
700 @param BaseAddress Start address of the segment
701 @param Length length of the segment
702 @param Capabilities The alterable attributes of a newly added entry
703 @param Attributes The attributes needs to be set
705 @retval EFI_INVALID_PARAMETER Length is 0 or address (length) not aligned when
707 @retval EFI_SUCCESS Action successfully done.
708 @retval EFI_UNSUPPORTED Could not find the proper descriptor on this
709 segment or set an upsupported attribute.
710 @retval EFI_ACCESS_DENIED Operate on an space non-exist or is used for an
712 @retval EFI_NOT_FOUND Free a non-using space or remove a non-exist
714 @retval EFI_OUT_OF_RESOURCES No buffer could be allocated.
715 @retval EFI_NOT_AVAILABLE_YET The attributes cannot be set because CPU architectural protocol
716 is not available yet.
721 IN EFI_GCD_MEMORY_TYPE GcdMemoryType
,
722 IN EFI_GCD_IO_TYPE GcdIoType
,
723 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
725 IN UINT64 Capabilities
,
732 EFI_GCD_MAP_ENTRY
*Entry
;
733 EFI_GCD_MAP_ENTRY
*TopEntry
;
734 EFI_GCD_MAP_ENTRY
*BottomEntry
;
735 LIST_ENTRY
*StartLink
;
737 UINT64 CpuArchAttributes
;
740 DEBUG ((DEBUG_GCD
, " Status = %r\n", EFI_INVALID_PARAMETER
));
741 return EFI_INVALID_PARAMETER
;
745 if ((Operation
& GCD_MEMORY_SPACE_OPERATION
) != 0) {
746 CoreAcquireGcdMemoryLock ();
747 Map
= &mGcdMemorySpaceMap
;
748 } else if ((Operation
& GCD_IO_SPACE_OPERATION
) != 0) {
749 CoreAcquireGcdIoLock ();
750 Map
= &mGcdIoSpaceMap
;
756 // Search for the list of descriptors that cover the range BaseAddress to BaseAddress+Length
758 Status
= CoreSearchGcdMapEntry (BaseAddress
, Length
, &StartLink
, &EndLink
, Map
);
759 if (EFI_ERROR (Status
)) {
760 Status
= EFI_UNSUPPORTED
;
764 ASSERT (StartLink
!= NULL
&& EndLink
!= NULL
);
767 // Verify that the list of descriptors are unallocated non-existent memory.
770 while (Link
!= EndLink
->ForwardLink
) {
771 Entry
= CR (Link
, EFI_GCD_MAP_ENTRY
, Link
, EFI_GCD_MAP_SIGNATURE
);
776 case GCD_ADD_MEMORY_OPERATION
:
777 if (Entry
->GcdMemoryType
!= EfiGcdMemoryTypeNonExistent
||
778 Entry
->ImageHandle
!= NULL
) {
779 Status
= EFI_ACCESS_DENIED
;
783 case GCD_ADD_IO_OPERATION
:
784 if (Entry
->GcdIoType
!= EfiGcdIoTypeNonExistent
||
785 Entry
->ImageHandle
!= NULL
) {
786 Status
= EFI_ACCESS_DENIED
;
793 case GCD_FREE_MEMORY_OPERATION
:
794 case GCD_FREE_IO_OPERATION
:
795 if (Entry
->ImageHandle
== NULL
) {
796 Status
= EFI_NOT_FOUND
;
803 case GCD_REMOVE_MEMORY_OPERATION
:
804 if (Entry
->GcdMemoryType
== EfiGcdMemoryTypeNonExistent
) {
805 Status
= EFI_NOT_FOUND
;
808 if (Entry
->ImageHandle
!= NULL
) {
809 Status
= EFI_ACCESS_DENIED
;
813 case GCD_REMOVE_IO_OPERATION
:
814 if (Entry
->GcdIoType
== EfiGcdIoTypeNonExistent
) {
815 Status
= EFI_NOT_FOUND
;
818 if (Entry
->ImageHandle
!= NULL
) {
819 Status
= EFI_ACCESS_DENIED
;
824 // Set attributes operation
826 case GCD_SET_ATTRIBUTES_MEMORY_OPERATION
:
827 if ((Attributes
& EFI_MEMORY_RUNTIME
) != 0) {
828 if ((BaseAddress
& EFI_PAGE_MASK
) != 0 || (Length
& EFI_PAGE_MASK
) != 0) {
829 Status
= EFI_INVALID_PARAMETER
;
833 if ((Entry
->Capabilities
& Attributes
) != Attributes
) {
834 Status
= EFI_UNSUPPORTED
;
839 // Set capabilities operation
841 case GCD_SET_CAPABILITIES_MEMORY_OPERATION
:
842 if ((BaseAddress
& EFI_PAGE_MASK
) != 0 || (Length
& EFI_PAGE_MASK
) != 0) {
843 Status
= EFI_INVALID_PARAMETER
;
848 // Current attributes must still be supported with new capabilities
850 if ((Capabilities
& Entry
->Attributes
) != Entry
->Attributes
) {
851 Status
= EFI_UNSUPPORTED
;
856 Link
= Link
->ForwardLink
;
860 // Allocate work space to perform this operation
862 Status
= CoreAllocateGcdMapEntry (&TopEntry
, &BottomEntry
);
863 if (EFI_ERROR (Status
)) {
864 Status
= EFI_OUT_OF_RESOURCES
;
867 ASSERT (TopEntry
!= NULL
&& BottomEntry
!= NULL
);
870 // Initialize CpuArchAttributes to suppress incorrect compiler/analyzer warnings.
872 CpuArchAttributes
= 0;
873 if (Operation
== GCD_SET_ATTRIBUTES_MEMORY_OPERATION
) {
875 // Call CPU Arch Protocol to attempt to set attributes on the range
877 CpuArchAttributes
= ConverToCpuArchAttributes (Attributes
);
879 // CPU arch attributes include page attributes and cache attributes.
880 // Only page attributes supports to be cleared, but not cache attributes.
881 // Caller is expected to use GetMemorySpaceDescriptor() to get the current
882 // attributes, AND/OR attributes, and then calls SetMemorySpaceAttributes()
883 // to set the new attributes.
884 // So 0 CPU arch attributes should not happen as memory should always have
885 // a cache attribute (no matter UC or WB, etc).
887 // Here, 0 CPU arch attributes will be filtered to be compatible with the
888 // case that caller just calls SetMemorySpaceAttributes() with none CPU
889 // arch attributes (for example, RUNTIME) as the purpose of the case is not
890 // to clear CPU arch attributes.
892 if (CpuArchAttributes
!= 0) {
894 Status
= EFI_NOT_AVAILABLE_YET
;
896 Status
= gCpu
->SetMemoryAttributes (
903 if (EFI_ERROR (Status
)) {
904 CoreFreePool (TopEntry
);
905 CoreFreePool (BottomEntry
);
912 // Convert/Insert the list of descriptors from StartLink to EndLink
915 while (Link
!= EndLink
->ForwardLink
) {
916 Entry
= CR (Link
, EFI_GCD_MAP_ENTRY
, Link
, EFI_GCD_MAP_SIGNATURE
);
917 CoreInsertGcdMapEntry (Link
, Entry
, BaseAddress
, Length
, TopEntry
, BottomEntry
);
922 case GCD_ADD_MEMORY_OPERATION
:
923 Entry
->GcdMemoryType
= GcdMemoryType
;
924 if (GcdMemoryType
== EfiGcdMemoryTypeMemoryMappedIo
) {
925 Entry
->Capabilities
= Capabilities
| EFI_MEMORY_RUNTIME
| EFI_MEMORY_PORT_IO
;
927 Entry
->Capabilities
= Capabilities
| EFI_MEMORY_RUNTIME
;
930 case GCD_ADD_IO_OPERATION
:
931 Entry
->GcdIoType
= GcdIoType
;
936 case GCD_FREE_MEMORY_OPERATION
:
937 case GCD_FREE_IO_OPERATION
:
938 Entry
->ImageHandle
= NULL
;
939 Entry
->DeviceHandle
= NULL
;
944 case GCD_REMOVE_MEMORY_OPERATION
:
945 Entry
->GcdMemoryType
= EfiGcdMemoryTypeNonExistent
;
946 Entry
->Capabilities
= 0;
948 case GCD_REMOVE_IO_OPERATION
:
949 Entry
->GcdIoType
= EfiGcdIoTypeNonExistent
;
952 // Set attributes operation
954 case GCD_SET_ATTRIBUTES_MEMORY_OPERATION
:
955 if (CpuArchAttributes
== 0) {
957 // Keep original CPU arch attributes when caller just calls
958 // SetMemorySpaceAttributes() with none CPU arch attributes (for example, RUNTIME).
960 Attributes
|= (Entry
->Attributes
& (EXCLUSIVE_MEMORY_ATTRIBUTES
| NONEXCLUSIVE_MEMORY_ATTRIBUTES
));
962 Entry
->Attributes
= Attributes
;
965 // Set capabilities operation
967 case GCD_SET_CAPABILITIES_MEMORY_OPERATION
:
968 Entry
->Capabilities
= Capabilities
;
971 Link
= Link
->ForwardLink
;
977 Status
= CoreCleanupGcdMapEntry (TopEntry
, BottomEntry
, StartLink
, EndLink
, Map
);
980 DEBUG ((DEBUG_GCD
, " Status = %r\n", Status
));
982 if ((Operation
& GCD_MEMORY_SPACE_OPERATION
) != 0) {
983 CoreReleaseGcdMemoryLock ();
984 CoreDumpGcdMemorySpaceMap (FALSE
);
986 if ((Operation
& GCD_IO_SPACE_OPERATION
) != 0) {
987 CoreReleaseGcdIoLock ();
988 CoreDumpGcdIoSpaceMap (FALSE
);
996 Check whether an entry could be used to allocate space.
998 @param Operation Allocate memory or IO
999 @param Entry The entry to be tested
1000 @param GcdMemoryType The desired memory type
1001 @param GcdIoType The desired IO type
1003 @retval EFI_NOT_FOUND The memory type does not match or there's an
1004 image handle on the entry.
1005 @retval EFI_UNSUPPORTED The operation unsupported.
1006 @retval EFI_SUCCESS It's ok for this entry to be used to allocate
1011 CoreAllocateSpaceCheckEntry (
1013 IN EFI_GCD_MAP_ENTRY
*Entry
,
1014 IN EFI_GCD_MEMORY_TYPE GcdMemoryType
,
1015 IN EFI_GCD_IO_TYPE GcdIoType
1018 if (Entry
->ImageHandle
!= NULL
) {
1019 return EFI_NOT_FOUND
;
1021 switch (Operation
) {
1022 case GCD_ALLOCATE_MEMORY_OPERATION
:
1023 if (Entry
->GcdMemoryType
!= GcdMemoryType
) {
1024 return EFI_NOT_FOUND
;
1027 case GCD_ALLOCATE_IO_OPERATION
:
1028 if (Entry
->GcdIoType
!= GcdIoType
) {
1029 return EFI_NOT_FOUND
;
1033 return EFI_UNSUPPORTED
;
1040 Allocate space on specified address and length.
1042 @param Operation The type of operation (memory or IO)
1043 @param GcdAllocateType The type of allocate operation
1044 @param GcdMemoryType The desired memory type
1045 @param GcdIoType The desired IO type
1046 @param Alignment Align with 2^Alignment
1047 @param Length Length to allocate
1048 @param BaseAddress Base address to allocate
1049 @param ImageHandle The image handle consume the allocated space.
1050 @param DeviceHandle The device handle consume the allocated space.
1052 @retval EFI_INVALID_PARAMETER Invalid parameter.
1053 @retval EFI_NOT_FOUND No descriptor for the desired space exists.
1054 @retval EFI_SUCCESS Space successfully allocated.
1060 IN EFI_GCD_ALLOCATE_TYPE GcdAllocateType
,
1061 IN EFI_GCD_MEMORY_TYPE GcdMemoryType
,
1062 IN EFI_GCD_IO_TYPE GcdIoType
,
1065 IN OUT EFI_PHYSICAL_ADDRESS
*BaseAddress
,
1066 IN EFI_HANDLE ImageHandle
,
1067 IN EFI_HANDLE DeviceHandle OPTIONAL
1071 EFI_PHYSICAL_ADDRESS AlignmentMask
;
1072 EFI_PHYSICAL_ADDRESS MaxAddress
;
1075 LIST_ENTRY
*SubLink
;
1076 EFI_GCD_MAP_ENTRY
*Entry
;
1077 EFI_GCD_MAP_ENTRY
*TopEntry
;
1078 EFI_GCD_MAP_ENTRY
*BottomEntry
;
1079 LIST_ENTRY
*StartLink
;
1080 LIST_ENTRY
*EndLink
;
1084 // Make sure parameters are valid
1086 if ((UINT32
)GcdAllocateType
>= EfiGcdMaxAllocateType
) {
1087 DEBUG ((DEBUG_GCD
, " Status = %r\n", EFI_INVALID_PARAMETER
));
1088 return EFI_INVALID_PARAMETER
;
1090 if ((UINT32
)GcdMemoryType
>= EfiGcdMemoryTypeMaximum
) {
1091 DEBUG ((DEBUG_GCD
, " Status = %r\n", EFI_INVALID_PARAMETER
));
1092 return EFI_INVALID_PARAMETER
;
1094 if ((UINT32
)GcdIoType
>= EfiGcdIoTypeMaximum
) {
1095 DEBUG ((DEBUG_GCD
, " Status = %r\n", EFI_INVALID_PARAMETER
));
1096 return EFI_INVALID_PARAMETER
;
1098 if (BaseAddress
== NULL
) {
1099 DEBUG ((DEBUG_GCD
, " Status = %r\n", EFI_INVALID_PARAMETER
));
1100 return EFI_INVALID_PARAMETER
;
1102 if (ImageHandle
== NULL
) {
1103 DEBUG ((DEBUG_GCD
, " Status = %r\n", EFI_INVALID_PARAMETER
));
1104 return EFI_INVALID_PARAMETER
;
1106 if (Alignment
>= 64) {
1107 DEBUG ((DEBUG_GCD
, " Status = %r\n", EFI_NOT_FOUND
));
1108 return EFI_NOT_FOUND
;
1111 DEBUG ((DEBUG_GCD
, " Status = %r\n", EFI_INVALID_PARAMETER
));
1112 return EFI_INVALID_PARAMETER
;
1116 if ((Operation
& GCD_MEMORY_SPACE_OPERATION
) != 0) {
1117 CoreAcquireGcdMemoryLock ();
1118 Map
= &mGcdMemorySpaceMap
;
1119 } else if ((Operation
& GCD_IO_SPACE_OPERATION
) != 0) {
1120 CoreAcquireGcdIoLock ();
1121 Map
= &mGcdIoSpaceMap
;
1130 // Compute alignment bit mask
1132 AlignmentMask
= LShiftU64 (1, Alignment
) - 1;
1134 if (GcdAllocateType
== EfiGcdAllocateAddress
) {
1136 // Verify that the BaseAddress passed in is aligned correctly
1138 if ((*BaseAddress
& AlignmentMask
) != 0) {
1139 Status
= EFI_NOT_FOUND
;
1144 // Search for the list of descriptors that cover the range BaseAddress to BaseAddress+Length
1146 Status
= CoreSearchGcdMapEntry (*BaseAddress
, Length
, &StartLink
, &EndLink
, Map
);
1147 if (EFI_ERROR (Status
)) {
1148 Status
= EFI_NOT_FOUND
;
1151 ASSERT (StartLink
!= NULL
&& EndLink
!= NULL
);
1154 // Verify that the list of descriptors are unallocated memory matching GcdMemoryType.
1157 while (Link
!= EndLink
->ForwardLink
) {
1158 Entry
= CR (Link
, EFI_GCD_MAP_ENTRY
, Link
, EFI_GCD_MAP_SIGNATURE
);
1159 Link
= Link
->ForwardLink
;
1160 Status
= CoreAllocateSpaceCheckEntry (Operation
, Entry
, GcdMemoryType
, GcdIoType
);
1161 if (EFI_ERROR (Status
)) {
1168 Entry
= CR (Map
->BackLink
, EFI_GCD_MAP_ENTRY
, Link
, EFI_GCD_MAP_SIGNATURE
);
1171 // Compute the maximum address to use in the search algorithm
1173 if (GcdAllocateType
== EfiGcdAllocateMaxAddressSearchBottomUp
||
1174 GcdAllocateType
== EfiGcdAllocateMaxAddressSearchTopDown
) {
1175 MaxAddress
= *BaseAddress
;
1177 MaxAddress
= Entry
->EndAddress
;
1181 // Verify that the list of descriptors are unallocated memory matching GcdMemoryType.
1183 if (GcdAllocateType
== EfiGcdAllocateMaxAddressSearchTopDown
||
1184 GcdAllocateType
== EfiGcdAllocateAnySearchTopDown
) {
1185 Link
= Map
->BackLink
;
1187 Link
= Map
->ForwardLink
;
1189 while (Link
!= Map
) {
1190 Entry
= CR (Link
, EFI_GCD_MAP_ENTRY
, Link
, EFI_GCD_MAP_SIGNATURE
);
1192 if (GcdAllocateType
== EfiGcdAllocateMaxAddressSearchTopDown
||
1193 GcdAllocateType
== EfiGcdAllocateAnySearchTopDown
) {
1194 Link
= Link
->BackLink
;
1196 Link
= Link
->ForwardLink
;
1199 Status
= CoreAllocateSpaceCheckEntry (Operation
, Entry
, GcdMemoryType
, GcdIoType
);
1200 if (EFI_ERROR (Status
)) {
1204 if (GcdAllocateType
== EfiGcdAllocateMaxAddressSearchTopDown
||
1205 GcdAllocateType
== EfiGcdAllocateAnySearchTopDown
) {
1206 if ((Entry
->BaseAddress
+ Length
) > MaxAddress
) {
1209 if (Length
> (Entry
->EndAddress
+ 1)) {
1210 Status
= EFI_NOT_FOUND
;
1213 if (Entry
->EndAddress
> MaxAddress
) {
1214 *BaseAddress
= MaxAddress
;
1216 *BaseAddress
= Entry
->EndAddress
;
1218 *BaseAddress
= (*BaseAddress
+ 1 - Length
) & (~AlignmentMask
);
1220 *BaseAddress
= (Entry
->BaseAddress
+ AlignmentMask
) & (~AlignmentMask
);
1221 if ((*BaseAddress
+ Length
- 1) > MaxAddress
) {
1222 Status
= EFI_NOT_FOUND
;
1228 // Search for the list of descriptors that cover the range BaseAddress to BaseAddress+Length
1230 Status
= CoreSearchGcdMapEntry (*BaseAddress
, Length
, &StartLink
, &EndLink
, Map
);
1231 if (EFI_ERROR (Status
)) {
1232 Status
= EFI_NOT_FOUND
;
1235 ASSERT (StartLink
!= NULL
&& EndLink
!= NULL
);
1239 // Verify that the list of descriptors are unallocated memory matching GcdMemoryType.
1242 SubLink
= StartLink
;
1243 while (SubLink
!= EndLink
->ForwardLink
) {
1244 Entry
= CR (SubLink
, EFI_GCD_MAP_ENTRY
, Link
, EFI_GCD_MAP_SIGNATURE
);
1245 Status
= CoreAllocateSpaceCheckEntry (Operation
, Entry
, GcdMemoryType
, GcdIoType
);
1246 if (EFI_ERROR (Status
)) {
1251 SubLink
= SubLink
->ForwardLink
;
1259 Status
= EFI_NOT_FOUND
;
1264 // Allocate work space to perform this operation
1266 Status
= CoreAllocateGcdMapEntry (&TopEntry
, &BottomEntry
);
1267 if (EFI_ERROR (Status
)) {
1268 Status
= EFI_OUT_OF_RESOURCES
;
1271 ASSERT (TopEntry
!= NULL
&& BottomEntry
!= NULL
);
1274 // Convert/Insert the list of descriptors from StartLink to EndLink
1277 while (Link
!= EndLink
->ForwardLink
) {
1278 Entry
= CR (Link
, EFI_GCD_MAP_ENTRY
, Link
, EFI_GCD_MAP_SIGNATURE
);
1279 CoreInsertGcdMapEntry (Link
, Entry
, *BaseAddress
, Length
, TopEntry
, BottomEntry
);
1280 Entry
->ImageHandle
= ImageHandle
;
1281 Entry
->DeviceHandle
= DeviceHandle
;
1282 Link
= Link
->ForwardLink
;
1288 Status
= CoreCleanupGcdMapEntry (TopEntry
, BottomEntry
, StartLink
, EndLink
, Map
);
1291 DEBUG ((DEBUG_GCD
, " Status = %r", Status
));
1292 if (!EFI_ERROR (Status
)) {
1293 DEBUG ((DEBUG_GCD
, " (BaseAddress = %016lx)", *BaseAddress
));
1295 DEBUG ((DEBUG_GCD
, "\n"));
1297 if ((Operation
& GCD_MEMORY_SPACE_OPERATION
) != 0) {
1298 CoreReleaseGcdMemoryLock ();
1299 CoreDumpGcdMemorySpaceMap (FALSE
);
1301 if ((Operation
& GCD_IO_SPACE_OPERATION
) !=0) {
1302 CoreReleaseGcdIoLock ();
1303 CoreDumpGcdIoSpaceMap (FALSE
);
1311 Add a segment of memory to GCD map.
1313 @param GcdMemoryType Memory type of the segment.
1314 @param BaseAddress Base address of the segment.
1315 @param Length Length of the segment.
1316 @param Capabilities alterable attributes of the segment.
1318 @retval EFI_INVALID_PARAMETER Invalid parameters.
1319 @retval EFI_SUCCESS Successfully add a segment of memory space.
1323 CoreInternalAddMemorySpace (
1324 IN EFI_GCD_MEMORY_TYPE GcdMemoryType
,
1325 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
1327 IN UINT64 Capabilities
1330 DEBUG ((DEBUG_GCD
, "GCD:AddMemorySpace(Base=%016lx,Length=%016lx)\n", BaseAddress
, Length
));
1331 DEBUG ((DEBUG_GCD
, " GcdMemoryType = %a\n", mGcdMemoryTypeNames
[MIN (GcdMemoryType
, EfiGcdMemoryTypeMaximum
)]));
1332 DEBUG ((DEBUG_GCD
, " Capabilities = %016lx\n", Capabilities
));
1335 // Make sure parameters are valid
1337 if (GcdMemoryType
<= EfiGcdMemoryTypeNonExistent
|| GcdMemoryType
>= EfiGcdMemoryTypeMaximum
) {
1338 return EFI_INVALID_PARAMETER
;
1341 return CoreConvertSpace (GCD_ADD_MEMORY_OPERATION
, GcdMemoryType
, (EFI_GCD_IO_TYPE
) 0, BaseAddress
, Length
, Capabilities
, 0);
1345 // GCD Core Services
1349 Allocates nonexistent memory, reserved memory, system memory, or memorymapped
1350 I/O resources from the global coherency domain of the processor.
1352 @param GcdAllocateType The type of allocate operation
1353 @param GcdMemoryType The desired memory type
1354 @param Alignment Align with 2^Alignment
1355 @param Length Length to allocate
1356 @param BaseAddress Base address to allocate
1357 @param ImageHandle The image handle consume the allocated space.
1358 @param DeviceHandle The device handle consume the allocated space.
1360 @retval EFI_INVALID_PARAMETER Invalid parameter.
1361 @retval EFI_NOT_FOUND No descriptor contains the desired space.
1362 @retval EFI_SUCCESS Memory space successfully allocated.
1367 CoreAllocateMemorySpace (
1368 IN EFI_GCD_ALLOCATE_TYPE GcdAllocateType
,
1369 IN EFI_GCD_MEMORY_TYPE GcdMemoryType
,
1372 IN OUT EFI_PHYSICAL_ADDRESS
*BaseAddress
,
1373 IN EFI_HANDLE ImageHandle
,
1374 IN EFI_HANDLE DeviceHandle OPTIONAL
1377 if (BaseAddress
!= NULL
) {
1378 DEBUG ((DEBUG_GCD
, "GCD:AllocateMemorySpace(Base=%016lx,Length=%016lx)\n", *BaseAddress
, Length
));
1380 DEBUG ((DEBUG_GCD
, "GCD:AllocateMemorySpace(Base=<NULL>,Length=%016lx)\n", Length
));
1382 DEBUG ((DEBUG_GCD
, " GcdAllocateType = %a\n", mGcdAllocationTypeNames
[MIN (GcdAllocateType
, EfiGcdMaxAllocateType
)]));
1383 DEBUG ((DEBUG_GCD
, " GcdMemoryType = %a\n", mGcdMemoryTypeNames
[MIN (GcdMemoryType
, EfiGcdMemoryTypeMaximum
)]));
1384 DEBUG ((DEBUG_GCD
, " Alignment = %016lx\n", LShiftU64 (1, Alignment
)));
1385 DEBUG ((DEBUG_GCD
, " ImageHandle = %p\n", ImageHandle
));
1386 DEBUG ((DEBUG_GCD
, " DeviceHandle = %p\n", DeviceHandle
));
1388 return CoreAllocateSpace (
1389 GCD_ALLOCATE_MEMORY_OPERATION
,
1392 (EFI_GCD_IO_TYPE
) 0,
1403 Adds reserved memory, system memory, or memory-mapped I/O resources to the
1404 global coherency domain of the processor.
1406 @param GcdMemoryType Memory type of the memory space.
1407 @param BaseAddress Base address of the memory space.
1408 @param Length Length of the memory space.
1409 @param Capabilities alterable attributes of the memory space.
1411 @retval EFI_SUCCESS Merged this memory space into GCD map.
1416 CoreAddMemorySpace (
1417 IN EFI_GCD_MEMORY_TYPE GcdMemoryType
,
1418 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
1420 IN UINT64 Capabilities
1424 EFI_PHYSICAL_ADDRESS PageBaseAddress
;
1427 Status
= CoreInternalAddMemorySpace (GcdMemoryType
, BaseAddress
, Length
, Capabilities
);
1429 if (!EFI_ERROR (Status
) && ((GcdMemoryType
== EfiGcdMemoryTypeSystemMemory
) || (GcdMemoryType
== EfiGcdMemoryTypeMoreReliable
))) {
1431 PageBaseAddress
= PageAlignAddress (BaseAddress
);
1432 PageLength
= PageAlignLength (BaseAddress
+ Length
- PageBaseAddress
);
1434 Status
= CoreAllocateMemorySpace (
1435 EfiGcdAllocateAddress
,
1440 gDxeCoreImageHandle
,
1444 if (!EFI_ERROR (Status
)) {
1445 CoreAddMemoryDescriptor (
1446 EfiConventionalMemory
,
1448 RShiftU64 (PageLength
, EFI_PAGE_SHIFT
),
1452 for (; PageLength
!= 0; PageLength
-= EFI_PAGE_SIZE
, PageBaseAddress
+= EFI_PAGE_SIZE
) {
1453 Status
= CoreAllocateMemorySpace (
1454 EfiGcdAllocateAddress
,
1459 gDxeCoreImageHandle
,
1463 if (!EFI_ERROR (Status
)) {
1464 CoreAddMemoryDescriptor (
1465 EfiConventionalMemory
,
1479 Frees nonexistent memory, reserved memory, system memory, or memory-mapped
1480 I/O resources from the global coherency domain of the processor.
1482 @param BaseAddress Base address of the memory space.
1483 @param Length Length of the memory space.
1485 @retval EFI_SUCCESS Space successfully freed.
1490 CoreFreeMemorySpace (
1491 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
1495 DEBUG ((DEBUG_GCD
, "GCD:FreeMemorySpace(Base=%016lx,Length=%016lx)\n", BaseAddress
, Length
));
1497 return CoreConvertSpace (GCD_FREE_MEMORY_OPERATION
, (EFI_GCD_MEMORY_TYPE
) 0, (EFI_GCD_IO_TYPE
) 0, BaseAddress
, Length
, 0, 0);
1502 Removes reserved memory, system memory, or memory-mapped I/O resources from
1503 the global coherency domain of the processor.
1505 @param BaseAddress Base address of the memory space.
1506 @param Length Length of the memory space.
1508 @retval EFI_SUCCESS Successfully remove a segment of memory space.
1513 CoreRemoveMemorySpace (
1514 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
1518 DEBUG ((DEBUG_GCD
, "GCD:RemoveMemorySpace(Base=%016lx,Length=%016lx)\n", BaseAddress
, Length
));
1520 return CoreConvertSpace (GCD_REMOVE_MEMORY_OPERATION
, (EFI_GCD_MEMORY_TYPE
) 0, (EFI_GCD_IO_TYPE
) 0, BaseAddress
, Length
, 0, 0);
1525 Build a memory descriptor according to an entry.
1527 @param Descriptor The descriptor to be built
1528 @param Entry According to this entry
1532 BuildMemoryDescriptor (
1533 IN OUT EFI_GCD_MEMORY_SPACE_DESCRIPTOR
*Descriptor
,
1534 IN EFI_GCD_MAP_ENTRY
*Entry
1537 Descriptor
->BaseAddress
= Entry
->BaseAddress
;
1538 Descriptor
->Length
= Entry
->EndAddress
- Entry
->BaseAddress
+ 1;
1539 Descriptor
->Capabilities
= Entry
->Capabilities
;
1540 Descriptor
->Attributes
= Entry
->Attributes
;
1541 Descriptor
->GcdMemoryType
= Entry
->GcdMemoryType
;
1542 Descriptor
->ImageHandle
= Entry
->ImageHandle
;
1543 Descriptor
->DeviceHandle
= Entry
->DeviceHandle
;
1548 Retrieves the descriptor for a memory region containing a specified address.
1550 @param BaseAddress Specified start address
1551 @param Descriptor Specified length
1553 @retval EFI_INVALID_PARAMETER Invalid parameter
1554 @retval EFI_SUCCESS Successfully get memory space descriptor.
1559 CoreGetMemorySpaceDescriptor (
1560 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
1561 OUT EFI_GCD_MEMORY_SPACE_DESCRIPTOR
*Descriptor
1565 LIST_ENTRY
*StartLink
;
1566 LIST_ENTRY
*EndLink
;
1567 EFI_GCD_MAP_ENTRY
*Entry
;
1570 // Make sure parameters are valid
1572 if (Descriptor
== NULL
) {
1573 return EFI_INVALID_PARAMETER
;
1576 CoreAcquireGcdMemoryLock ();
1579 // Search for the list of descriptors that contain BaseAddress
1581 Status
= CoreSearchGcdMapEntry (BaseAddress
, 1, &StartLink
, &EndLink
, &mGcdMemorySpaceMap
);
1582 if (EFI_ERROR (Status
)) {
1583 Status
= EFI_NOT_FOUND
;
1585 ASSERT (StartLink
!= NULL
&& EndLink
!= NULL
);
1587 // Copy the contents of the found descriptor into Descriptor
1589 Entry
= CR (StartLink
, EFI_GCD_MAP_ENTRY
, Link
, EFI_GCD_MAP_SIGNATURE
);
1590 BuildMemoryDescriptor (Descriptor
, Entry
);
1593 CoreReleaseGcdMemoryLock ();
1600 Modifies the attributes for a memory region in the global coherency domain of the
1603 @param BaseAddress Specified start address
1604 @param Length Specified length
1605 @param Attributes Specified attributes
1607 @retval EFI_SUCCESS The attributes were set for the memory region.
1608 @retval EFI_INVALID_PARAMETER Length is zero.
1609 @retval EFI_UNSUPPORTED The processor does not support one or more bytes of the memory
1610 resource range specified by BaseAddress and Length.
1611 @retval EFI_UNSUPPORTED The bit mask of attributes is not support for the memory resource
1612 range specified by BaseAddress and Length.
1613 @retval EFI_ACCESS_DEFINED The attributes for the memory resource range specified by
1614 BaseAddress and Length cannot be modified.
1615 @retval EFI_OUT_OF_RESOURCES There are not enough system resources to modify the attributes of
1616 the memory resource range.
1617 @retval EFI_NOT_AVAILABLE_YET The attributes cannot be set because CPU architectural protocol is
1623 CoreSetMemorySpaceAttributes (
1624 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
1626 IN UINT64 Attributes
1629 DEBUG ((DEBUG_GCD
, "GCD:SetMemorySpaceAttributes(Base=%016lx,Length=%016lx)\n", BaseAddress
, Length
));
1630 DEBUG ((DEBUG_GCD
, " Attributes = %016lx\n", Attributes
));
1632 return CoreConvertSpace (GCD_SET_ATTRIBUTES_MEMORY_OPERATION
, (EFI_GCD_MEMORY_TYPE
) 0, (EFI_GCD_IO_TYPE
) 0, BaseAddress
, Length
, 0, Attributes
);
1637 Modifies the capabilities for a memory region in the global coherency domain of the
1640 @param BaseAddress The physical address that is the start address of a memory region.
1641 @param Length The size in bytes of the memory region.
1642 @param Capabilities The bit mask of capabilities that the memory region supports.
1644 @retval EFI_SUCCESS The capabilities were set for the memory region.
1645 @retval EFI_INVALID_PARAMETER Length is zero.
1646 @retval EFI_UNSUPPORTED The capabilities specified by Capabilities do not include the
1647 memory region attributes currently in use.
1648 @retval EFI_ACCESS_DENIED The capabilities for the memory resource range specified by
1649 BaseAddress and Length cannot be modified.
1650 @retval EFI_OUT_OF_RESOURCES There are not enough system resources to modify the capabilities
1651 of the memory resource range.
1655 CoreSetMemorySpaceCapabilities (
1656 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
1658 IN UINT64 Capabilities
1663 DEBUG ((DEBUG_GCD
, "GCD:CoreSetMemorySpaceCapabilities(Base=%016lx,Length=%016lx)\n", BaseAddress
, Length
));
1664 DEBUG ((DEBUG_GCD
, " Capabilities = %016lx\n", Capabilities
));
1666 Status
= CoreConvertSpace (GCD_SET_CAPABILITIES_MEMORY_OPERATION
, (EFI_GCD_MEMORY_TYPE
) 0, (EFI_GCD_IO_TYPE
) 0, BaseAddress
, Length
, Capabilities
, 0);
1667 if (!EFI_ERROR(Status
)) {
1668 CoreUpdateMemoryAttributes(BaseAddress
, RShiftU64(Length
, EFI_PAGE_SHIFT
), Capabilities
& (~EFI_MEMORY_RUNTIME
));
1676 Returns a map of the memory resources in the global coherency domain of the
1679 @param NumberOfDescriptors Number of descriptors.
1680 @param MemorySpaceMap Descriptor array
1682 @retval EFI_INVALID_PARAMETER Invalid parameter
1683 @retval EFI_OUT_OF_RESOURCES No enough buffer to allocate
1684 @retval EFI_SUCCESS Successfully get memory space map.
1689 CoreGetMemorySpaceMap (
1690 OUT UINTN
*NumberOfDescriptors
,
1691 OUT EFI_GCD_MEMORY_SPACE_DESCRIPTOR
**MemorySpaceMap
1696 EFI_GCD_MAP_ENTRY
*Entry
;
1697 EFI_GCD_MEMORY_SPACE_DESCRIPTOR
*Descriptor
;
1700 // Make sure parameters are valid
1702 if (NumberOfDescriptors
== NULL
) {
1703 return EFI_INVALID_PARAMETER
;
1705 if (MemorySpaceMap
== NULL
) {
1706 return EFI_INVALID_PARAMETER
;
1709 CoreAcquireGcdMemoryLock ();
1712 // Count the number of descriptors
1714 *NumberOfDescriptors
= CoreCountGcdMapEntry (&mGcdMemorySpaceMap
);
1717 // Allocate the MemorySpaceMap
1719 *MemorySpaceMap
= AllocatePool (*NumberOfDescriptors
* sizeof (EFI_GCD_MEMORY_SPACE_DESCRIPTOR
));
1720 if (*MemorySpaceMap
== NULL
) {
1721 Status
= EFI_OUT_OF_RESOURCES
;
1726 // Fill in the MemorySpaceMap
1728 Descriptor
= *MemorySpaceMap
;
1729 Link
= mGcdMemorySpaceMap
.ForwardLink
;
1730 while (Link
!= &mGcdMemorySpaceMap
) {
1731 Entry
= CR (Link
, EFI_GCD_MAP_ENTRY
, Link
, EFI_GCD_MAP_SIGNATURE
);
1732 BuildMemoryDescriptor (Descriptor
, Entry
);
1734 Link
= Link
->ForwardLink
;
1736 Status
= EFI_SUCCESS
;
1739 CoreReleaseGcdMemoryLock ();
1745 Adds reserved I/O or I/O resources to the global coherency domain of the processor.
1747 @param GcdIoType IO type of the segment.
1748 @param BaseAddress Base address of the segment.
1749 @param Length Length of the segment.
1751 @retval EFI_SUCCESS Merged this segment into GCD map.
1752 @retval EFI_INVALID_PARAMETER Parameter not valid
1758 IN EFI_GCD_IO_TYPE GcdIoType
,
1759 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
1763 DEBUG ((DEBUG_GCD
, "GCD:AddIoSpace(Base=%016lx,Length=%016lx)\n", BaseAddress
, Length
));
1764 DEBUG ((DEBUG_GCD
, " GcdIoType = %a\n", mGcdIoTypeNames
[MIN (GcdIoType
, EfiGcdIoTypeMaximum
)]));
1767 // Make sure parameters are valid
1769 if (GcdIoType
<= EfiGcdIoTypeNonExistent
|| GcdIoType
>= EfiGcdIoTypeMaximum
) {
1770 return EFI_INVALID_PARAMETER
;
1772 return CoreConvertSpace (GCD_ADD_IO_OPERATION
, (EFI_GCD_MEMORY_TYPE
) 0, GcdIoType
, BaseAddress
, Length
, 0, 0);
1777 Allocates nonexistent I/O, reserved I/O, or I/O resources from the global coherency
1778 domain of the processor.
1780 @param GcdAllocateType The type of allocate operation
1781 @param GcdIoType The desired IO type
1782 @param Alignment Align with 2^Alignment
1783 @param Length Length to allocate
1784 @param BaseAddress Base address to allocate
1785 @param ImageHandle The image handle consume the allocated space.
1786 @param DeviceHandle The device handle consume the allocated space.
1788 @retval EFI_INVALID_PARAMETER Invalid parameter.
1789 @retval EFI_NOT_FOUND No descriptor contains the desired space.
1790 @retval EFI_SUCCESS IO space successfully allocated.
1795 CoreAllocateIoSpace (
1796 IN EFI_GCD_ALLOCATE_TYPE GcdAllocateType
,
1797 IN EFI_GCD_IO_TYPE GcdIoType
,
1800 IN OUT EFI_PHYSICAL_ADDRESS
*BaseAddress
,
1801 IN EFI_HANDLE ImageHandle
,
1802 IN EFI_HANDLE DeviceHandle OPTIONAL
1805 if (BaseAddress
!= NULL
) {
1806 DEBUG ((DEBUG_GCD
, "GCD:AllocateIoSpace(Base=%016lx,Length=%016lx)\n", *BaseAddress
, Length
));
1808 DEBUG ((DEBUG_GCD
, "GCD:AllocateIoSpace(Base=<NULL>,Length=%016lx)\n", Length
));
1810 DEBUG ((DEBUG_GCD
, " GcdAllocateType = %a\n", mGcdAllocationTypeNames
[MIN (GcdAllocateType
, EfiGcdMaxAllocateType
)]));
1811 DEBUG ((DEBUG_GCD
, " GcdIoType = %a\n", mGcdIoTypeNames
[MIN (GcdIoType
, EfiGcdIoTypeMaximum
)]));
1812 DEBUG ((DEBUG_GCD
, " Alignment = %016lx\n", LShiftU64 (1, Alignment
)));
1813 DEBUG ((DEBUG_GCD
, " ImageHandle = %p\n", ImageHandle
));
1814 DEBUG ((DEBUG_GCD
, " DeviceHandle = %p\n", DeviceHandle
));
1816 return CoreAllocateSpace (
1817 GCD_ALLOCATE_IO_OPERATION
,
1819 (EFI_GCD_MEMORY_TYPE
) 0,
1831 Frees nonexistent I/O, reserved I/O, or I/O resources from the global coherency
1832 domain of the processor.
1834 @param BaseAddress Base address of the segment.
1835 @param Length Length of the segment.
1837 @retval EFI_SUCCESS Space successfully freed.
1843 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
1847 DEBUG ((DEBUG_GCD
, "GCD:FreeIoSpace(Base=%016lx,Length=%016lx)\n", BaseAddress
, Length
));
1849 return CoreConvertSpace (GCD_FREE_IO_OPERATION
, (EFI_GCD_MEMORY_TYPE
) 0, (EFI_GCD_IO_TYPE
) 0, BaseAddress
, Length
, 0, 0);
1854 Removes reserved I/O or I/O resources from the global coherency domain of the
1857 @param BaseAddress Base address of the segment.
1858 @param Length Length of the segment.
1860 @retval EFI_SUCCESS Successfully removed a segment of IO space.
1866 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
1870 DEBUG ((DEBUG_GCD
, "GCD:RemoveIoSpace(Base=%016lx,Length=%016lx)\n", BaseAddress
, Length
));
1872 return CoreConvertSpace (GCD_REMOVE_IO_OPERATION
, (EFI_GCD_MEMORY_TYPE
) 0, (EFI_GCD_IO_TYPE
) 0, BaseAddress
, Length
, 0, 0);
1877 Build a IO descriptor according to an entry.
1879 @param Descriptor The descriptor to be built
1880 @param Entry According to this entry
1885 IN EFI_GCD_IO_SPACE_DESCRIPTOR
*Descriptor
,
1886 IN EFI_GCD_MAP_ENTRY
*Entry
1889 Descriptor
->BaseAddress
= Entry
->BaseAddress
;
1890 Descriptor
->Length
= Entry
->EndAddress
- Entry
->BaseAddress
+ 1;
1891 Descriptor
->GcdIoType
= Entry
->GcdIoType
;
1892 Descriptor
->ImageHandle
= Entry
->ImageHandle
;
1893 Descriptor
->DeviceHandle
= Entry
->DeviceHandle
;
1898 Retrieves the descriptor for an I/O region containing a specified address.
1900 @param BaseAddress Specified start address
1901 @param Descriptor Specified length
1903 @retval EFI_INVALID_PARAMETER Descriptor is NULL.
1904 @retval EFI_SUCCESS Successfully get the IO space descriptor.
1909 CoreGetIoSpaceDescriptor (
1910 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
1911 OUT EFI_GCD_IO_SPACE_DESCRIPTOR
*Descriptor
1915 LIST_ENTRY
*StartLink
;
1916 LIST_ENTRY
*EndLink
;
1917 EFI_GCD_MAP_ENTRY
*Entry
;
1920 // Make sure parameters are valid
1922 if (Descriptor
== NULL
) {
1923 return EFI_INVALID_PARAMETER
;
1926 CoreAcquireGcdIoLock ();
1929 // Search for the list of descriptors that contain BaseAddress
1931 Status
= CoreSearchGcdMapEntry (BaseAddress
, 1, &StartLink
, &EndLink
, &mGcdIoSpaceMap
);
1932 if (EFI_ERROR (Status
)) {
1933 Status
= EFI_NOT_FOUND
;
1935 ASSERT (StartLink
!= NULL
&& EndLink
!= NULL
);
1937 // Copy the contents of the found descriptor into Descriptor
1939 Entry
= CR (StartLink
, EFI_GCD_MAP_ENTRY
, Link
, EFI_GCD_MAP_SIGNATURE
);
1940 BuildIoDescriptor (Descriptor
, Entry
);
1943 CoreReleaseGcdIoLock ();
1950 Returns a map of the I/O resources in the global coherency domain of the processor.
1952 @param NumberOfDescriptors Number of descriptors.
1953 @param IoSpaceMap Descriptor array
1955 @retval EFI_INVALID_PARAMETER Invalid parameter
1956 @retval EFI_OUT_OF_RESOURCES No enough buffer to allocate
1957 @retval EFI_SUCCESS Successfully get IO space map.
1963 OUT UINTN
*NumberOfDescriptors
,
1964 OUT EFI_GCD_IO_SPACE_DESCRIPTOR
**IoSpaceMap
1969 EFI_GCD_MAP_ENTRY
*Entry
;
1970 EFI_GCD_IO_SPACE_DESCRIPTOR
*Descriptor
;
1973 // Make sure parameters are valid
1975 if (NumberOfDescriptors
== NULL
) {
1976 return EFI_INVALID_PARAMETER
;
1978 if (IoSpaceMap
== NULL
) {
1979 return EFI_INVALID_PARAMETER
;
1982 CoreAcquireGcdIoLock ();
1985 // Count the number of descriptors
1987 *NumberOfDescriptors
= CoreCountGcdMapEntry (&mGcdIoSpaceMap
);
1990 // Allocate the IoSpaceMap
1992 *IoSpaceMap
= AllocatePool (*NumberOfDescriptors
* sizeof (EFI_GCD_IO_SPACE_DESCRIPTOR
));
1993 if (*IoSpaceMap
== NULL
) {
1994 Status
= EFI_OUT_OF_RESOURCES
;
1999 // Fill in the IoSpaceMap
2001 Descriptor
= *IoSpaceMap
;
2002 Link
= mGcdIoSpaceMap
.ForwardLink
;
2003 while (Link
!= &mGcdIoSpaceMap
) {
2004 Entry
= CR (Link
, EFI_GCD_MAP_ENTRY
, Link
, EFI_GCD_MAP_SIGNATURE
);
2005 BuildIoDescriptor (Descriptor
, Entry
);
2007 Link
= Link
->ForwardLink
;
2009 Status
= EFI_SUCCESS
;
2012 CoreReleaseGcdIoLock ();
2018 Converts a Resource Descriptor HOB attributes mask to an EFI Memory Descriptor
2021 @param GcdMemoryType Type of resource in the GCD memory map.
2022 @param Attributes The attribute mask in the Resource Descriptor
2025 @return The capabilities mask for an EFI Memory Descriptor.
2029 CoreConvertResourceDescriptorHobAttributesToCapabilities (
2030 EFI_GCD_MEMORY_TYPE GcdMemoryType
,
2034 UINT64 Capabilities
;
2035 GCD_ATTRIBUTE_CONVERSION_ENTRY
*Conversion
;
2038 // Convert the Resource HOB Attributes to an EFI Memory Capabilities mask
2040 for (Capabilities
= 0, Conversion
= mAttributeConversionTable
; Conversion
->Attribute
!= 0; Conversion
++) {
2041 if (Conversion
->Memory
|| ((GcdMemoryType
!= EfiGcdMemoryTypeSystemMemory
) && (GcdMemoryType
!= EfiGcdMemoryTypeMoreReliable
))) {
2042 if (Attributes
& Conversion
->Attribute
) {
2043 Capabilities
|= Conversion
->Capability
;
2048 return Capabilities
;
2052 Calculate total memory bin size neeeded.
2054 @return The total memory bin size neeeded.
2058 CalculateTotalMemoryBinSizeNeeded (
2066 // Loop through each memory type in the order specified by the gMemoryTypeInformation[] array
2069 for (Index
= 0; gMemoryTypeInformation
[Index
].Type
!= EfiMaxMemoryType
; Index
++) {
2070 TotalSize
+= LShiftU64 (gMemoryTypeInformation
[Index
].NumberOfPages
, EFI_PAGE_SHIFT
);
2077 External function. Initializes memory services based on the memory
2078 descriptor HOBs. This function is responsible for priming the memory
2079 map, so memory allocations and resource allocations can be made.
2080 The first part of this function can not depend on any memory services
2081 until at least one memory descriptor is provided to the memory services.
2083 @param HobStart The start address of the HOB.
2084 @param MemoryBaseAddress Start address of memory region found to init DXE
2086 @param MemoryLength Length of memory region found to init DXE core.
2088 @retval EFI_SUCCESS Memory services successfully initialized.
2092 CoreInitializeMemoryServices (
2094 OUT EFI_PHYSICAL_ADDRESS
*MemoryBaseAddress
,
2095 OUT UINT64
*MemoryLength
2098 EFI_PEI_HOB_POINTERS Hob
;
2099 EFI_MEMORY_TYPE_INFORMATION
*EfiMemoryTypeInformation
;
2102 EFI_HOB_HANDOFF_INFO_TABLE
*PhitHob
;
2103 EFI_HOB_RESOURCE_DESCRIPTOR
*ResourceHob
;
2104 EFI_HOB_RESOURCE_DESCRIPTOR
*PhitResourceHob
;
2105 EFI_PHYSICAL_ADDRESS BaseAddress
;
2108 UINT64 Capabilities
;
2109 EFI_PHYSICAL_ADDRESS TestedMemoryBaseAddress
;
2110 UINT64 TestedMemoryLength
;
2111 EFI_PHYSICAL_ADDRESS HighAddress
;
2112 EFI_HOB_GUID_TYPE
*GuidHob
;
2113 UINT32 ReservedCodePageNumber
;
2114 UINT64 MinimalMemorySizeNeeded
;
2117 // Point at the first HOB. This must be the PHIT HOB.
2119 Hob
.Raw
= *HobStart
;
2120 ASSERT (GET_HOB_TYPE (Hob
) == EFI_HOB_TYPE_HANDOFF
);
2123 // Initialize the spin locks and maps in the memory services.
2124 // Also fill in the memory services into the EFI Boot Services Table
2126 CoreInitializePool ();
2129 // Initialize Local Variables
2131 PhitResourceHob
= NULL
;
2138 // Cache the PHIT HOB for later use
2140 PhitHob
= Hob
.HandoffInformationTable
;
2142 if (PcdGet64(PcdLoadModuleAtFixAddressEnable
) != 0) {
2143 ReservedCodePageNumber
= PcdGet32(PcdLoadFixAddressRuntimeCodePageNumber
);
2144 ReservedCodePageNumber
+= PcdGet32(PcdLoadFixAddressBootTimeCodePageNumber
);
2147 // cache the Top address for loading modules at Fixed Address
2149 gLoadModuleAtFixAddressConfigurationTable
.DxeCodeTopAddress
= PhitHob
->EfiMemoryTop
2150 + EFI_PAGES_TO_SIZE(ReservedCodePageNumber
);
2153 // See if a Memory Type Information HOB is available
2155 GuidHob
= GetFirstGuidHob (&gEfiMemoryTypeInformationGuid
);
2156 if (GuidHob
!= NULL
) {
2157 EfiMemoryTypeInformation
= GET_GUID_HOB_DATA (GuidHob
);
2158 DataSize
= GET_GUID_HOB_DATA_SIZE (GuidHob
);
2159 if (EfiMemoryTypeInformation
!= NULL
&& DataSize
> 0 && DataSize
<= (EfiMaxMemoryType
+ 1) * sizeof (EFI_MEMORY_TYPE_INFORMATION
)) {
2160 CopyMem (&gMemoryTypeInformation
, EfiMemoryTypeInformation
, DataSize
);
2165 // Include the total memory bin size needed to make sure memory bin could be allocated successfully.
2167 MinimalMemorySizeNeeded
= MINIMUM_INITIAL_MEMORY_SIZE
+ CalculateTotalMemoryBinSizeNeeded ();
2170 // Find the Resource Descriptor HOB that contains PHIT range EfiFreeMemoryBottom..EfiFreeMemoryTop
2173 for (Hob
.Raw
= *HobStart
; !END_OF_HOB_LIST(Hob
); Hob
.Raw
= GET_NEXT_HOB(Hob
)) {
2175 // Skip all HOBs except Resource Descriptor HOBs
2177 if (GET_HOB_TYPE (Hob
) != EFI_HOB_TYPE_RESOURCE_DESCRIPTOR
) {
2182 // Skip Resource Descriptor HOBs that do not describe tested system memory
2184 ResourceHob
= Hob
.ResourceDescriptor
;
2185 if (ResourceHob
->ResourceType
!= EFI_RESOURCE_SYSTEM_MEMORY
) {
2188 if ((ResourceHob
->ResourceAttribute
& MEMORY_ATTRIBUTE_MASK
) != TESTED_MEMORY_ATTRIBUTES
) {
2193 // Skip Resource Descriptor HOBs that do not contain the PHIT range EfiFreeMemoryBottom..EfiFreeMemoryTop
2195 if (PhitHob
->EfiFreeMemoryBottom
< ResourceHob
->PhysicalStart
) {
2198 if (PhitHob
->EfiFreeMemoryTop
> (ResourceHob
->PhysicalStart
+ ResourceHob
->ResourceLength
)) {
2203 // Cache the resource descriptor HOB for the memory region described by the PHIT HOB
2205 PhitResourceHob
= ResourceHob
;
2209 // Compute range between PHIT EfiMemoryTop and the end of the Resource Descriptor HOB
2211 Attributes
= PhitResourceHob
->ResourceAttribute
;
2212 BaseAddress
= PageAlignAddress (PhitHob
->EfiMemoryTop
);
2213 Length
= PageAlignLength (ResourceHob
->PhysicalStart
+ ResourceHob
->ResourceLength
- BaseAddress
);
2214 if (Length
< MinimalMemorySizeNeeded
) {
2216 // If that range is not large enough to intialize the DXE Core, then
2217 // Compute range between PHIT EfiFreeMemoryBottom and PHIT EfiFreeMemoryTop
2219 BaseAddress
= PageAlignAddress (PhitHob
->EfiFreeMemoryBottom
);
2220 Length
= PageAlignLength (PhitHob
->EfiFreeMemoryTop
- BaseAddress
);
2221 if (Length
< MinimalMemorySizeNeeded
) {
2223 // If that range is not large enough to intialize the DXE Core, then
2224 // Compute range between the start of the Resource Descriptor HOB and the start of the HOB List
2226 BaseAddress
= PageAlignAddress (ResourceHob
->PhysicalStart
);
2227 Length
= PageAlignLength ((UINT64
)((UINTN
)*HobStart
- BaseAddress
));
2234 // Assert if a resource descriptor HOB for the memory region described by the PHIT was not found
2239 // Take the range in the resource descriptor HOB for the memory region described
2240 // by the PHIT as higher priority if it is big enough. It can make the memory bin
2241 // allocated to be at the same memory region with PHIT that has more better compatibility
2242 // to avoid memory fragmentation for some code practices assume and allocate <4G ACPI memory.
2244 if (Length
< MinimalMemorySizeNeeded
) {
2246 // Search all the resource descriptor HOBs from the highest possible addresses down for a memory
2247 // region that is big enough to initialize the DXE core. Always skip the PHIT Resource HOB.
2248 // The max address must be within the physically addressible range for the processor.
2250 HighAddress
= MAX_ADDRESS
;
2251 for (Hob
.Raw
= *HobStart
; !END_OF_HOB_LIST(Hob
); Hob
.Raw
= GET_NEXT_HOB(Hob
)) {
2253 // Skip the Resource Descriptor HOB that contains the PHIT
2255 if (Hob
.ResourceDescriptor
== PhitResourceHob
) {
2259 // Skip all HOBs except Resource Descriptor HOBs
2261 if (GET_HOB_TYPE (Hob
) != EFI_HOB_TYPE_RESOURCE_DESCRIPTOR
) {
2266 // Skip Resource Descriptor HOBs that do not describe tested system memory below MAX_ADDRESS
2268 ResourceHob
= Hob
.ResourceDescriptor
;
2269 if (ResourceHob
->ResourceType
!= EFI_RESOURCE_SYSTEM_MEMORY
) {
2272 if ((ResourceHob
->ResourceAttribute
& MEMORY_ATTRIBUTE_MASK
) != TESTED_MEMORY_ATTRIBUTES
) {
2275 if ((ResourceHob
->PhysicalStart
+ ResourceHob
->ResourceLength
) > (EFI_PHYSICAL_ADDRESS
)MAX_ADDRESS
) {
2280 // Skip Resource Descriptor HOBs that are below a previously found Resource Descriptor HOB
2282 if (HighAddress
!= (EFI_PHYSICAL_ADDRESS
)MAX_ADDRESS
&& ResourceHob
->PhysicalStart
<= HighAddress
) {
2287 // Skip Resource Descriptor HOBs that are not large enough to initilize the DXE Core
2289 TestedMemoryBaseAddress
= PageAlignAddress (ResourceHob
->PhysicalStart
);
2290 TestedMemoryLength
= PageAlignLength (ResourceHob
->PhysicalStart
+ ResourceHob
->ResourceLength
- TestedMemoryBaseAddress
);
2291 if (TestedMemoryLength
< MinimalMemorySizeNeeded
) {
2296 // Save the range described by the Resource Descriptor that is large enough to initilize the DXE Core
2298 BaseAddress
= TestedMemoryBaseAddress
;
2299 Length
= TestedMemoryLength
;
2300 Attributes
= ResourceHob
->ResourceAttribute
;
2301 HighAddress
= ResourceHob
->PhysicalStart
;
2305 DEBUG ((EFI_D_INFO
, "CoreInitializeMemoryServices:\n"));
2306 DEBUG ((EFI_D_INFO
, " BaseAddress - 0x%lx Length - 0x%lx MinimalMemorySizeNeeded - 0x%lx\n", BaseAddress
, Length
, MinimalMemorySizeNeeded
));
2309 // If no memory regions are found that are big enough to initialize the DXE core, then ASSERT().
2311 ASSERT (Length
>= MinimalMemorySizeNeeded
);
2314 // Convert the Resource HOB Attributes to an EFI Memory Capabilities mask
2316 if ((Attributes
& EFI_RESOURCE_ATTRIBUTE_MORE_RELIABLE
) == EFI_RESOURCE_ATTRIBUTE_MORE_RELIABLE
) {
2317 Capabilities
= CoreConvertResourceDescriptorHobAttributesToCapabilities (EfiGcdMemoryTypeMoreReliable
, Attributes
);
2319 Capabilities
= CoreConvertResourceDescriptorHobAttributesToCapabilities (EfiGcdMemoryTypeSystemMemory
, Attributes
);
2323 // Declare the very first memory region, so the EFI Memory Services are available.
2325 CoreAddMemoryDescriptor (
2326 EfiConventionalMemory
,
2328 RShiftU64 (Length
, EFI_PAGE_SHIFT
),
2332 *MemoryBaseAddress
= BaseAddress
;
2333 *MemoryLength
= Length
;
2340 External function. Initializes the GCD and memory services based on the memory
2341 descriptor HOBs. This function is responsible for priming the GCD map and the
2342 memory map, so memory allocations and resource allocations can be made. The
2343 HobStart will be relocated to a pool buffer.
2345 @param HobStart The start address of the HOB
2346 @param MemoryBaseAddress Start address of memory region found to init DXE
2348 @param MemoryLength Length of memory region found to init DXE core.
2350 @retval EFI_SUCCESS GCD services successfully initialized.
2354 CoreInitializeGcdServices (
2355 IN OUT VOID
**HobStart
,
2356 IN EFI_PHYSICAL_ADDRESS MemoryBaseAddress
,
2357 IN UINT64 MemoryLength
2360 EFI_PEI_HOB_POINTERS Hob
;
2362 EFI_HOB_HANDOFF_INFO_TABLE
*PhitHob
;
2363 UINT8 SizeOfMemorySpace
;
2364 UINT8 SizeOfIoSpace
;
2365 EFI_HOB_RESOURCE_DESCRIPTOR
*ResourceHob
;
2366 EFI_PHYSICAL_ADDRESS BaseAddress
;
2369 EFI_GCD_MAP_ENTRY
*Entry
;
2370 EFI_GCD_MEMORY_TYPE GcdMemoryType
;
2371 EFI_GCD_IO_TYPE GcdIoType
;
2372 EFI_GCD_MEMORY_SPACE_DESCRIPTOR Descriptor
;
2373 EFI_HOB_MEMORY_ALLOCATION
*MemoryHob
;
2374 EFI_HOB_FIRMWARE_VOLUME
*FirmwareVolumeHob
;
2375 UINTN NumberOfDescriptors
;
2376 EFI_GCD_MEMORY_SPACE_DESCRIPTOR
*MemorySpaceMap
;
2378 UINT64 Capabilities
;
2379 EFI_HOB_CPU
* CpuHob
;
2380 EFI_GCD_MEMORY_SPACE_DESCRIPTOR
*MemorySpaceMapHobList
;
2383 // Cache the PHIT HOB for later use
2385 PhitHob
= (EFI_HOB_HANDOFF_INFO_TABLE
*)(*HobStart
);
2388 // Get the number of address lines in the I/O and Memory space for the CPU
2390 CpuHob
= GetFirstHob (EFI_HOB_TYPE_CPU
);
2391 ASSERT (CpuHob
!= NULL
);
2392 SizeOfMemorySpace
= CpuHob
->SizeOfMemorySpace
;
2393 SizeOfIoSpace
= CpuHob
->SizeOfIoSpace
;
2396 // Initialize the GCD Memory Space Map
2398 Entry
= AllocateCopyPool (sizeof (EFI_GCD_MAP_ENTRY
), &mGcdMemorySpaceMapEntryTemplate
);
2399 ASSERT (Entry
!= NULL
);
2401 Entry
->EndAddress
= LShiftU64 (1, SizeOfMemorySpace
) - 1;
2403 InsertHeadList (&mGcdMemorySpaceMap
, &Entry
->Link
);
2405 CoreDumpGcdMemorySpaceMap (TRUE
);
2408 // Initialize the GCD I/O Space Map
2410 Entry
= AllocateCopyPool (sizeof (EFI_GCD_MAP_ENTRY
), &mGcdIoSpaceMapEntryTemplate
);
2411 ASSERT (Entry
!= NULL
);
2413 Entry
->EndAddress
= LShiftU64 (1, SizeOfIoSpace
) - 1;
2415 InsertHeadList (&mGcdIoSpaceMap
, &Entry
->Link
);
2417 CoreDumpGcdIoSpaceMap (TRUE
);
2420 // Walk the HOB list and add all resource descriptors to the GCD
2422 for (Hob
.Raw
= *HobStart
; !END_OF_HOB_LIST(Hob
); Hob
.Raw
= GET_NEXT_HOB(Hob
)) {
2424 GcdMemoryType
= EfiGcdMemoryTypeNonExistent
;
2425 GcdIoType
= EfiGcdIoTypeNonExistent
;
2427 if (GET_HOB_TYPE (Hob
) == EFI_HOB_TYPE_RESOURCE_DESCRIPTOR
) {
2429 ResourceHob
= Hob
.ResourceDescriptor
;
2431 switch (ResourceHob
->ResourceType
) {
2432 case EFI_RESOURCE_SYSTEM_MEMORY
:
2433 if ((ResourceHob
->ResourceAttribute
& MEMORY_ATTRIBUTE_MASK
) == TESTED_MEMORY_ATTRIBUTES
) {
2434 if ((ResourceHob
->ResourceAttribute
& EFI_RESOURCE_ATTRIBUTE_MORE_RELIABLE
) == EFI_RESOURCE_ATTRIBUTE_MORE_RELIABLE
) {
2435 GcdMemoryType
= EfiGcdMemoryTypeMoreReliable
;
2437 GcdMemoryType
= EfiGcdMemoryTypeSystemMemory
;
2440 if ((ResourceHob
->ResourceAttribute
& MEMORY_ATTRIBUTE_MASK
) == INITIALIZED_MEMORY_ATTRIBUTES
) {
2441 GcdMemoryType
= EfiGcdMemoryTypeReserved
;
2443 if ((ResourceHob
->ResourceAttribute
& MEMORY_ATTRIBUTE_MASK
) == PRESENT_MEMORY_ATTRIBUTES
) {
2444 GcdMemoryType
= EfiGcdMemoryTypeReserved
;
2446 if ((ResourceHob
->ResourceAttribute
& EFI_RESOURCE_ATTRIBUTE_PERSISTENT
) == EFI_RESOURCE_ATTRIBUTE_PERSISTENT
) {
2447 GcdMemoryType
= EfiGcdMemoryTypePersistent
;
2450 case EFI_RESOURCE_MEMORY_MAPPED_IO
:
2451 case EFI_RESOURCE_FIRMWARE_DEVICE
:
2452 GcdMemoryType
= EfiGcdMemoryTypeMemoryMappedIo
;
2454 case EFI_RESOURCE_MEMORY_MAPPED_IO_PORT
:
2455 case EFI_RESOURCE_MEMORY_RESERVED
:
2456 GcdMemoryType
= EfiGcdMemoryTypeReserved
;
2458 case EFI_RESOURCE_IO
:
2459 GcdIoType
= EfiGcdIoTypeIo
;
2461 case EFI_RESOURCE_IO_RESERVED
:
2462 GcdIoType
= EfiGcdIoTypeReserved
;
2466 if (GcdMemoryType
!= EfiGcdMemoryTypeNonExistent
) {
2468 // Validate the Resource HOB Attributes
2470 CoreValidateResourceDescriptorHobAttributes (ResourceHob
->ResourceAttribute
);
2473 // Convert the Resource HOB Attributes to an EFI Memory Capabilities mask
2475 Capabilities
= CoreConvertResourceDescriptorHobAttributesToCapabilities (
2477 ResourceHob
->ResourceAttribute
2480 Status
= CoreInternalAddMemorySpace (
2482 ResourceHob
->PhysicalStart
,
2483 ResourceHob
->ResourceLength
,
2488 if (GcdIoType
!= EfiGcdIoTypeNonExistent
) {
2489 Status
= CoreAddIoSpace (
2491 ResourceHob
->PhysicalStart
,
2492 ResourceHob
->ResourceLength
2499 // Allocate first memory region from the GCD by the DXE core
2501 Status
= CoreGetMemorySpaceDescriptor (MemoryBaseAddress
, &Descriptor
);
2502 if (!EFI_ERROR (Status
)) {
2503 ASSERT ((Descriptor
.GcdMemoryType
== EfiGcdMemoryTypeSystemMemory
) ||
2504 (Descriptor
.GcdMemoryType
== EfiGcdMemoryTypeMoreReliable
));
2505 Status
= CoreAllocateMemorySpace (
2506 EfiGcdAllocateAddress
,
2507 Descriptor
.GcdMemoryType
,
2511 gDxeCoreImageHandle
,
2517 // Walk the HOB list and allocate all memory space that is consumed by memory allocation HOBs,
2518 // and Firmware Volume HOBs. Also update the EFI Memory Map with the memory allocation HOBs.
2520 for (Hob
.Raw
= *HobStart
; !END_OF_HOB_LIST(Hob
); Hob
.Raw
= GET_NEXT_HOB(Hob
)) {
2521 if (GET_HOB_TYPE (Hob
) == EFI_HOB_TYPE_MEMORY_ALLOCATION
) {
2522 MemoryHob
= Hob
.MemoryAllocation
;
2523 BaseAddress
= MemoryHob
->AllocDescriptor
.MemoryBaseAddress
;
2524 Status
= CoreGetMemorySpaceDescriptor (BaseAddress
, &Descriptor
);
2525 if (!EFI_ERROR (Status
)) {
2526 Status
= CoreAllocateMemorySpace (
2527 EfiGcdAllocateAddress
,
2528 Descriptor
.GcdMemoryType
,
2530 MemoryHob
->AllocDescriptor
.MemoryLength
,
2532 gDxeCoreImageHandle
,
2535 if (!EFI_ERROR (Status
) &&
2536 ((Descriptor
.GcdMemoryType
== EfiGcdMemoryTypeSystemMemory
) ||
2537 (Descriptor
.GcdMemoryType
== EfiGcdMemoryTypeMoreReliable
))) {
2538 CoreAddMemoryDescriptor (
2539 MemoryHob
->AllocDescriptor
.MemoryType
,
2540 MemoryHob
->AllocDescriptor
.MemoryBaseAddress
,
2541 RShiftU64 (MemoryHob
->AllocDescriptor
.MemoryLength
, EFI_PAGE_SHIFT
),
2542 Descriptor
.Capabilities
& (~EFI_MEMORY_RUNTIME
)
2548 if (GET_HOB_TYPE (Hob
) == EFI_HOB_TYPE_FV
) {
2549 FirmwareVolumeHob
= Hob
.FirmwareVolume
;
2550 BaseAddress
= FirmwareVolumeHob
->BaseAddress
;
2551 Status
= CoreAllocateMemorySpace (
2552 EfiGcdAllocateAddress
,
2553 EfiGcdMemoryTypeMemoryMappedIo
,
2555 FirmwareVolumeHob
->Length
,
2557 gDxeCoreImageHandle
,
2564 // Add and allocate the remaining unallocated system memory to the memory services.
2566 Status
= CoreGetMemorySpaceMap (&NumberOfDescriptors
, &MemorySpaceMap
);
2567 ASSERT (Status
== EFI_SUCCESS
);
2569 MemorySpaceMapHobList
= NULL
;
2570 for (Index
= 0; Index
< NumberOfDescriptors
; Index
++) {
2571 if ((MemorySpaceMap
[Index
].GcdMemoryType
== EfiGcdMemoryTypeSystemMemory
) ||
2572 (MemorySpaceMap
[Index
].GcdMemoryType
== EfiGcdMemoryTypeMoreReliable
)) {
2573 if (MemorySpaceMap
[Index
].ImageHandle
== NULL
) {
2574 BaseAddress
= PageAlignAddress (MemorySpaceMap
[Index
].BaseAddress
);
2575 Length
= PageAlignLength (MemorySpaceMap
[Index
].BaseAddress
+ MemorySpaceMap
[Index
].Length
- BaseAddress
);
2576 if (Length
== 0 || MemorySpaceMap
[Index
].BaseAddress
+ MemorySpaceMap
[Index
].Length
< BaseAddress
) {
2579 if (((UINTN
) MemorySpaceMap
[Index
].BaseAddress
<= (UINTN
) (*HobStart
)) &&
2580 ((UINTN
) (MemorySpaceMap
[Index
].BaseAddress
+ MemorySpaceMap
[Index
].Length
) >= (UINTN
) PhitHob
->EfiFreeMemoryBottom
)) {
2582 // Skip the memory space that covers HOB List, it should be processed
2583 // after HOB List relocation to avoid the resources allocated by others
2584 // to corrupt HOB List before its relocation.
2586 MemorySpaceMapHobList
= &MemorySpaceMap
[Index
];
2589 CoreAddMemoryDescriptor (
2590 EfiConventionalMemory
,
2592 RShiftU64 (Length
, EFI_PAGE_SHIFT
),
2593 MemorySpaceMap
[Index
].Capabilities
& (~EFI_MEMORY_RUNTIME
)
2595 Status
= CoreAllocateMemorySpace (
2596 EfiGcdAllocateAddress
,
2597 MemorySpaceMap
[Index
].GcdMemoryType
,
2601 gDxeCoreImageHandle
,
2609 // Relocate HOB List to an allocated pool buffer.
2610 // The relocation should be at after all the tested memory resources added
2611 // (except the memory space that covers HOB List) to the memory services,
2612 // because the memory resource found in CoreInitializeMemoryServices()
2613 // may have not enough remaining resource for HOB List.
2615 NewHobList
= AllocateCopyPool (
2616 (UINTN
) PhitHob
->EfiFreeMemoryBottom
- (UINTN
) (*HobStart
),
2619 ASSERT (NewHobList
!= NULL
);
2621 *HobStart
= NewHobList
;
2622 gHobList
= NewHobList
;
2624 if (MemorySpaceMapHobList
!= NULL
) {
2626 // Add and allocate the memory space that covers HOB List to the memory services
2627 // after HOB List relocation.
2629 BaseAddress
= PageAlignAddress (MemorySpaceMapHobList
->BaseAddress
);
2630 Length
= PageAlignLength (MemorySpaceMapHobList
->BaseAddress
+ MemorySpaceMapHobList
->Length
- BaseAddress
);
2631 CoreAddMemoryDescriptor (
2632 EfiConventionalMemory
,
2634 RShiftU64 (Length
, EFI_PAGE_SHIFT
),
2635 MemorySpaceMapHobList
->Capabilities
& (~EFI_MEMORY_RUNTIME
)
2637 Status
= CoreAllocateMemorySpace (
2638 EfiGcdAllocateAddress
,
2639 MemorySpaceMapHobList
->GcdMemoryType
,
2643 gDxeCoreImageHandle
,
2648 CoreFreePool (MemorySpaceMap
);