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 - 2017, 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 EXCLUSIVE_MEMORY_ATTRIBUTES (EFI_MEMORY_UC | EFI_MEMORY_WC | \
44 EFI_MEMORY_WT | EFI_MEMORY_WB | \
45 EFI_MEMORY_WP | EFI_MEMORY_UCE)
47 #define NONEXCLUSIVE_MEMORY_ATTRIBUTES (EFI_MEMORY_XP | EFI_MEMORY_RP | \
50 #define INVALID_CPU_ARCH_ATTRIBUTES 0xffffffff
55 EFI_LOCK mGcdMemorySpaceLock
= EFI_INITIALIZE_LOCK_VARIABLE (TPL_NOTIFY
);
56 EFI_LOCK mGcdIoSpaceLock
= EFI_INITIALIZE_LOCK_VARIABLE (TPL_NOTIFY
);
57 LIST_ENTRY mGcdMemorySpaceMap
= INITIALIZE_LIST_HEAD_VARIABLE (mGcdMemorySpaceMap
);
58 LIST_ENTRY mGcdIoSpaceMap
= INITIALIZE_LIST_HEAD_VARIABLE (mGcdIoSpaceMap
);
60 EFI_GCD_MAP_ENTRY mGcdMemorySpaceMapEntryTemplate
= {
61 EFI_GCD_MAP_SIGNATURE
,
70 EfiGcdMemoryTypeNonExistent
,
76 EFI_GCD_MAP_ENTRY mGcdIoSpaceMapEntryTemplate
= {
77 EFI_GCD_MAP_SIGNATURE
,
86 (EFI_GCD_MEMORY_TYPE
) 0,
87 EfiGcdIoTypeNonExistent
,
92 GCD_ATTRIBUTE_CONVERSION_ENTRY mAttributeConversionTable
[] = {
93 { EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE
, EFI_MEMORY_UC
, TRUE
},
94 { EFI_RESOURCE_ATTRIBUTE_UNCACHED_EXPORTED
, EFI_MEMORY_UCE
, TRUE
},
95 { EFI_RESOURCE_ATTRIBUTE_WRITE_COMBINEABLE
, EFI_MEMORY_WC
, TRUE
},
96 { EFI_RESOURCE_ATTRIBUTE_WRITE_THROUGH_CACHEABLE
, EFI_MEMORY_WT
, TRUE
},
97 { EFI_RESOURCE_ATTRIBUTE_WRITE_BACK_CACHEABLE
, EFI_MEMORY_WB
, TRUE
},
98 { EFI_RESOURCE_ATTRIBUTE_READ_PROTECTABLE
, EFI_MEMORY_RP
, TRUE
},
99 { EFI_RESOURCE_ATTRIBUTE_WRITE_PROTECTABLE
, EFI_MEMORY_WP
, TRUE
},
100 { EFI_RESOURCE_ATTRIBUTE_EXECUTION_PROTECTABLE
, EFI_MEMORY_XP
, TRUE
},
101 { EFI_RESOURCE_ATTRIBUTE_READ_ONLY_PROTECTABLE
, EFI_MEMORY_RO
, TRUE
},
102 { EFI_RESOURCE_ATTRIBUTE_PRESENT
, EFI_MEMORY_PRESENT
, FALSE
},
103 { EFI_RESOURCE_ATTRIBUTE_INITIALIZED
, EFI_MEMORY_INITIALIZED
, FALSE
},
104 { EFI_RESOURCE_ATTRIBUTE_TESTED
, EFI_MEMORY_TESTED
, FALSE
},
105 { EFI_RESOURCE_ATTRIBUTE_PERSISTABLE
, EFI_MEMORY_NV
, TRUE
},
106 { EFI_RESOURCE_ATTRIBUTE_MORE_RELIABLE
, EFI_MEMORY_MORE_RELIABLE
, TRUE
},
111 /// Lookup table used to print GCD Memory Space Map
113 GLOBAL_REMOVE_IF_UNREFERENCED CONST CHAR8
*mGcdMemoryTypeNames
[] = {
114 "NonExist ", // EfiGcdMemoryTypeNonExistent
115 "Reserved ", // EfiGcdMemoryTypeReserved
116 "SystemMem", // EfiGcdMemoryTypeSystemMemory
117 "MMIO ", // EfiGcdMemoryTypeMemoryMappedIo
118 "PersisMem", // EfiGcdMemoryTypePersistent
119 "MoreRelia", // EfiGcdMemoryTypeMoreReliable
120 "Unknown " // EfiGcdMemoryTypeMaximum
124 /// Lookup table used to print GCD I/O Space Map
126 GLOBAL_REMOVE_IF_UNREFERENCED CONST CHAR8
*mGcdIoTypeNames
[] = {
127 "NonExist", // EfiGcdIoTypeNonExistent
128 "Reserved", // EfiGcdIoTypeReserved
129 "I/O ", // EfiGcdIoTypeIo
130 "Unknown " // EfiGcdIoTypeMaximum
134 /// Lookup table used to print GCD Allocation Types
136 GLOBAL_REMOVE_IF_UNREFERENCED CONST CHAR8
*mGcdAllocationTypeNames
[] = {
137 "AnySearchBottomUp ", // EfiGcdAllocateAnySearchBottomUp
138 "MaxAddressSearchBottomUp ", // EfiGcdAllocateMaxAddressSearchBottomUp
139 "AtAddress ", // EfiGcdAllocateAddress
140 "AnySearchTopDown ", // EfiGcdAllocateAnySearchTopDown
141 "MaxAddressSearchTopDown ", // EfiGcdAllocateMaxAddressSearchTopDown
142 "Unknown " // EfiGcdMaxAllocateType
146 Dump the entire contents if the GCD Memory Space Map using DEBUG() macros when
147 PcdDebugPrintErrorLevel has the DEBUG_GCD bit set.
149 @param InitialMap TRUE if the initial GCD Memory Map is being dumped. Otherwise, FALSE.
154 CoreDumpGcdMemorySpaceMap (
160 UINTN NumberOfDescriptors
;
161 EFI_GCD_MEMORY_SPACE_DESCRIPTOR
*MemorySpaceMap
;
164 Status
= CoreGetMemorySpaceMap (&NumberOfDescriptors
, &MemorySpaceMap
);
165 ASSERT (Status
== EFI_SUCCESS
&& MemorySpaceMap
!= NULL
);
168 DEBUG ((DEBUG_GCD
, "GCD:Initial GCD Memory Space Map\n"));
170 DEBUG ((DEBUG_GCD
, "GCDMemType Range Capabilities Attributes \n"));
171 DEBUG ((DEBUG_GCD
, "========== ================================= ================ ================\n"));
172 for (Index
= 0; Index
< NumberOfDescriptors
; Index
++) {
173 DEBUG ((DEBUG_GCD
, "%a %016lx-%016lx %016lx %016lx%c\n",
174 mGcdMemoryTypeNames
[MIN (MemorySpaceMap
[Index
].GcdMemoryType
, EfiGcdMemoryTypeMaximum
)],
175 MemorySpaceMap
[Index
].BaseAddress
,
176 MemorySpaceMap
[Index
].BaseAddress
+ MemorySpaceMap
[Index
].Length
- 1,
177 MemorySpaceMap
[Index
].Capabilities
,
178 MemorySpaceMap
[Index
].Attributes
,
179 MemorySpaceMap
[Index
].ImageHandle
== NULL
? ' ' : '*'
182 DEBUG ((DEBUG_GCD
, "\n"));
183 FreePool (MemorySpaceMap
);
188 Dump the entire contents if the GCD I/O Space Map using DEBUG() macros when
189 PcdDebugPrintErrorLevel has the DEBUG_GCD bit set.
191 @param InitialMap TRUE if the initial GCD I/O Map is being dumped. Otherwise, FALSE.
196 CoreDumpGcdIoSpaceMap (
202 UINTN NumberOfDescriptors
;
203 EFI_GCD_IO_SPACE_DESCRIPTOR
*IoSpaceMap
;
206 Status
= CoreGetIoSpaceMap (&NumberOfDescriptors
, &IoSpaceMap
);
207 ASSERT (Status
== EFI_SUCCESS
&& IoSpaceMap
!= NULL
);
210 DEBUG ((DEBUG_GCD
, "GCD:Initial GCD I/O Space Map\n"));
213 DEBUG ((DEBUG_GCD
, "GCDIoType Range \n"));
214 DEBUG ((DEBUG_GCD
, "========== =================================\n"));
215 for (Index
= 0; Index
< NumberOfDescriptors
; Index
++) {
216 DEBUG ((DEBUG_GCD
, "%a %016lx-%016lx%c\n",
217 mGcdIoTypeNames
[MIN (IoSpaceMap
[Index
].GcdIoType
, EfiGcdIoTypeMaximum
)],
218 IoSpaceMap
[Index
].BaseAddress
,
219 IoSpaceMap
[Index
].BaseAddress
+ IoSpaceMap
[Index
].Length
- 1,
220 IoSpaceMap
[Index
].ImageHandle
== NULL
? ' ' : '*'
223 DEBUG ((DEBUG_GCD
, "\n"));
224 FreePool (IoSpaceMap
);
229 Validate resource descriptor HOB's attributes.
231 If Attributes includes some memory resource's settings, it should include
232 the corresponding capabilites also.
234 @param Attributes Resource descriptor HOB attributes.
238 CoreValidateResourceDescriptorHobAttributes (
242 ASSERT (((Attributes
& EFI_RESOURCE_ATTRIBUTE_READ_PROTECTED
) == 0) ||
243 ((Attributes
& EFI_RESOURCE_ATTRIBUTE_READ_PROTECTABLE
) != 0));
244 ASSERT (((Attributes
& EFI_RESOURCE_ATTRIBUTE_WRITE_PROTECTED
) == 0) ||
245 ((Attributes
& EFI_RESOURCE_ATTRIBUTE_WRITE_PROTECTABLE
) != 0));
246 ASSERT (((Attributes
& EFI_RESOURCE_ATTRIBUTE_EXECUTION_PROTECTED
) == 0) ||
247 ((Attributes
& EFI_RESOURCE_ATTRIBUTE_EXECUTION_PROTECTABLE
) != 0));
248 ASSERT (((Attributes
& EFI_RESOURCE_ATTRIBUTE_READ_ONLY_PROTECTED
) == 0) ||
249 ((Attributes
& EFI_RESOURCE_ATTRIBUTE_READ_ONLY_PROTECTABLE
) != 0));
250 ASSERT (((Attributes
& EFI_RESOURCE_ATTRIBUTE_PERSISTENT
) == 0) ||
251 ((Attributes
& EFI_RESOURCE_ATTRIBUTE_PERSISTABLE
) != 0));
255 Acquire memory lock on mGcdMemorySpaceLock.
259 CoreAcquireGcdMemoryLock (
263 CoreAcquireLock (&mGcdMemorySpaceLock
);
269 Release memory lock on mGcdMemorySpaceLock.
273 CoreReleaseGcdMemoryLock (
277 CoreReleaseLock (&mGcdMemorySpaceLock
);
283 Acquire memory lock on mGcdIoSpaceLock.
287 CoreAcquireGcdIoLock (
291 CoreAcquireLock (&mGcdIoSpaceLock
);
296 Release memory lock on mGcdIoSpaceLock.
300 CoreReleaseGcdIoLock (
304 CoreReleaseLock (&mGcdIoSpaceLock
);
310 // GCD Initialization Worker Functions
313 Aligns a value to the specified boundary.
315 @param Value 64 bit value to align
316 @param Alignment Log base 2 of the boundary to align Value to
317 @param RoundUp TRUE if Value is to be rounded up to the nearest
318 aligned boundary. FALSE is Value is to be
319 rounded down to the nearest aligned boundary.
321 @return A 64 bit value is the aligned to the value nearest Value with an alignment by Alignment.
331 UINT64 AlignmentMask
;
333 AlignmentMask
= LShiftU64 (1, Alignment
) - 1;
335 Value
+= AlignmentMask
;
337 return Value
& (~AlignmentMask
);
342 Aligns address to the page boundary.
344 @param Value 64 bit address to align
346 @return A 64 bit value is the aligned to the value nearest Value with an alignment by Alignment.
354 return AlignValue (Value
, EFI_PAGE_SHIFT
, TRUE
);
359 Aligns length to the page boundary.
361 @param Value 64 bit length to align
363 @return A 64 bit value is the aligned to the value nearest Value with an alignment by Alignment.
371 return AlignValue (Value
, EFI_PAGE_SHIFT
, FALSE
);
375 // GCD Memory Space Worker Functions
379 Allocate pool for two entries.
381 @param TopEntry An entry of GCD map
382 @param BottomEntry An entry of GCD map
384 @retval EFI_OUT_OF_RESOURCES No enough buffer to be allocated.
385 @retval EFI_SUCCESS Both entries successfully allocated.
389 CoreAllocateGcdMapEntry (
390 IN OUT EFI_GCD_MAP_ENTRY
**TopEntry
,
391 IN OUT EFI_GCD_MAP_ENTRY
**BottomEntry
394 *TopEntry
= AllocateZeroPool (sizeof (EFI_GCD_MAP_ENTRY
));
395 if (*TopEntry
== NULL
) {
396 return EFI_OUT_OF_RESOURCES
;
399 *BottomEntry
= AllocateZeroPool (sizeof (EFI_GCD_MAP_ENTRY
));
400 if (*BottomEntry
== NULL
) {
401 CoreFreePool (*TopEntry
);
402 return EFI_OUT_OF_RESOURCES
;
410 Internal function. Inserts a new descriptor into a sorted list
412 @param Link The linked list to insert the range BaseAddress
414 @param Entry A pointer to the entry that is inserted
415 @param BaseAddress The base address of the new range
416 @param Length The length of the new range in bytes
417 @param TopEntry Top pad entry to insert if needed.
418 @param BottomEntry Bottom pad entry to insert if needed.
420 @retval EFI_SUCCESS The new range was inserted into the linked list
424 CoreInsertGcdMapEntry (
426 IN EFI_GCD_MAP_ENTRY
*Entry
,
427 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
429 IN EFI_GCD_MAP_ENTRY
*TopEntry
,
430 IN EFI_GCD_MAP_ENTRY
*BottomEntry
433 ASSERT (Length
!= 0);
435 if (BaseAddress
> Entry
->BaseAddress
) {
436 ASSERT (BottomEntry
->Signature
== 0);
438 CopyMem (BottomEntry
, Entry
, sizeof (EFI_GCD_MAP_ENTRY
));
439 Entry
->BaseAddress
= BaseAddress
;
440 BottomEntry
->EndAddress
= BaseAddress
- 1;
441 InsertTailList (Link
, &BottomEntry
->Link
);
444 if ((BaseAddress
+ Length
- 1) < Entry
->EndAddress
) {
445 ASSERT (TopEntry
->Signature
== 0);
447 CopyMem (TopEntry
, Entry
, sizeof (EFI_GCD_MAP_ENTRY
));
448 TopEntry
->BaseAddress
= BaseAddress
+ Length
;
449 Entry
->EndAddress
= BaseAddress
+ Length
- 1;
450 InsertHeadList (Link
, &TopEntry
->Link
);
458 Merge the Gcd region specified by Link and its adjacent entry.
460 @param Link Specify the entry to be merged (with its
462 @param Forward Direction (forward or backward).
465 @retval EFI_SUCCESS Successfully returned.
466 @retval EFI_UNSUPPORTED These adjacent regions could not merge.
470 CoreMergeGcdMapEntry (
476 LIST_ENTRY
*AdjacentLink
;
477 EFI_GCD_MAP_ENTRY
*Entry
;
478 EFI_GCD_MAP_ENTRY
*AdjacentEntry
;
481 // Get adjacent entry
484 AdjacentLink
= Link
->ForwardLink
;
486 AdjacentLink
= Link
->BackLink
;
490 // If AdjacentLink is the head of the list, then no merge can be performed
492 if (AdjacentLink
== Map
) {
496 Entry
= CR (Link
, EFI_GCD_MAP_ENTRY
, Link
, EFI_GCD_MAP_SIGNATURE
);
497 AdjacentEntry
= CR (AdjacentLink
, EFI_GCD_MAP_ENTRY
, Link
, EFI_GCD_MAP_SIGNATURE
);
499 if (Entry
->Capabilities
!= AdjacentEntry
->Capabilities
) {
500 return EFI_UNSUPPORTED
;
502 if (Entry
->Attributes
!= AdjacentEntry
->Attributes
) {
503 return EFI_UNSUPPORTED
;
505 if (Entry
->GcdMemoryType
!= AdjacentEntry
->GcdMemoryType
) {
506 return EFI_UNSUPPORTED
;
508 if (Entry
->GcdIoType
!= AdjacentEntry
->GcdIoType
) {
509 return EFI_UNSUPPORTED
;
511 if (Entry
->ImageHandle
!= AdjacentEntry
->ImageHandle
) {
512 return EFI_UNSUPPORTED
;
514 if (Entry
->DeviceHandle
!= AdjacentEntry
->DeviceHandle
) {
515 return EFI_UNSUPPORTED
;
519 Entry
->EndAddress
= AdjacentEntry
->EndAddress
;
521 Entry
->BaseAddress
= AdjacentEntry
->BaseAddress
;
523 RemoveEntryList (AdjacentLink
);
524 CoreFreePool (AdjacentEntry
);
531 Merge adjacent entries on total chain.
533 @param TopEntry Top entry of GCD map.
534 @param BottomEntry Bottom entry of GCD map.
535 @param StartLink Start link of the list for this loop.
536 @param EndLink End link of the list for this loop.
539 @retval EFI_SUCCESS GCD map successfully cleaned up.
543 CoreCleanupGcdMapEntry (
544 IN EFI_GCD_MAP_ENTRY
*TopEntry
,
545 IN EFI_GCD_MAP_ENTRY
*BottomEntry
,
546 IN LIST_ENTRY
*StartLink
,
547 IN LIST_ENTRY
*EndLink
,
553 if (TopEntry
->Signature
== 0) {
554 CoreFreePool (TopEntry
);
556 if (BottomEntry
->Signature
== 0) {
557 CoreFreePool (BottomEntry
);
561 while (Link
!= EndLink
->ForwardLink
) {
562 CoreMergeGcdMapEntry (Link
, FALSE
, Map
);
563 Link
= Link
->ForwardLink
;
565 CoreMergeGcdMapEntry (EndLink
, TRUE
, Map
);
572 Search a segment of memory space in GCD map. The result is a range of GCD entry list.
574 @param BaseAddress The start address of the segment.
575 @param Length The length of the segment.
576 @param StartLink The first GCD entry involves this segment of
578 @param EndLink The first GCD entry involves this segment of
580 @param Map Points to the start entry to search.
582 @retval EFI_SUCCESS Successfully found the entry.
583 @retval EFI_NOT_FOUND Not found.
587 CoreSearchGcdMapEntry (
588 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
590 OUT LIST_ENTRY
**StartLink
,
591 OUT LIST_ENTRY
**EndLink
,
596 EFI_GCD_MAP_ENTRY
*Entry
;
598 ASSERT (Length
!= 0);
603 Link
= Map
->ForwardLink
;
604 while (Link
!= Map
) {
605 Entry
= CR (Link
, EFI_GCD_MAP_ENTRY
, Link
, EFI_GCD_MAP_SIGNATURE
);
606 if (BaseAddress
>= Entry
->BaseAddress
&& BaseAddress
<= Entry
->EndAddress
) {
609 if (*StartLink
!= NULL
) {
610 if ((BaseAddress
+ Length
- 1) >= Entry
->BaseAddress
&&
611 (BaseAddress
+ Length
- 1) <= Entry
->EndAddress
) {
616 Link
= Link
->ForwardLink
;
619 return EFI_NOT_FOUND
;
624 Count the amount of GCD map entries.
626 @param Map Points to the start entry to do the count loop.
632 CoreCountGcdMapEntry (
640 Link
= Map
->ForwardLink
;
641 while (Link
!= Map
) {
643 Link
= Link
->ForwardLink
;
652 Return the memory attribute specified by Attributes
654 @param Attributes A num with some attribute bits on.
656 @return The enum value of memory attribute.
660 ConverToCpuArchAttributes (
664 UINT64 CpuArchAttributes
;
666 if ((Attributes
& ~(EXCLUSIVE_MEMORY_ATTRIBUTES
|
667 NONEXCLUSIVE_MEMORY_ATTRIBUTES
)) != 0) {
668 return INVALID_CPU_ARCH_ATTRIBUTES
;
671 CpuArchAttributes
= Attributes
& NONEXCLUSIVE_MEMORY_ATTRIBUTES
;
673 if ( (Attributes
& EFI_MEMORY_UC
) == EFI_MEMORY_UC
) {
674 CpuArchAttributes
|= EFI_MEMORY_UC
;
675 } else if ( (Attributes
& EFI_MEMORY_WC
) == EFI_MEMORY_WC
) {
676 CpuArchAttributes
|= EFI_MEMORY_WC
;
677 } else if ( (Attributes
& EFI_MEMORY_WT
) == EFI_MEMORY_WT
) {
678 CpuArchAttributes
|= EFI_MEMORY_WT
;
679 } else if ( (Attributes
& EFI_MEMORY_WB
) == EFI_MEMORY_WB
) {
680 CpuArchAttributes
|= EFI_MEMORY_WB
;
681 } else if ( (Attributes
& EFI_MEMORY_UCE
) == EFI_MEMORY_UCE
) {
682 CpuArchAttributes
|= EFI_MEMORY_UCE
;
683 } else if ( (Attributes
& EFI_MEMORY_WP
) == EFI_MEMORY_WP
) {
684 CpuArchAttributes
|= EFI_MEMORY_WP
;
687 return CpuArchAttributes
;
692 Do operation on a segment of memory space specified (add, free, remove, change attribute ...).
694 @param Operation The type of the operation
695 @param GcdMemoryType Additional information for the operation
696 @param GcdIoType Additional information for the operation
697 @param BaseAddress Start address of the segment
698 @param Length length of the segment
699 @param Capabilities The alterable attributes of a newly added entry
700 @param Attributes The attributes needs to be set
702 @retval EFI_INVALID_PARAMETER Length is 0 or address (length) not aligned when
704 @retval EFI_SUCCESS Action successfully done.
705 @retval EFI_UNSUPPORTED Could not find the proper descriptor on this
706 segment or set an upsupported attribute.
707 @retval EFI_ACCESS_DENIED Operate on an space non-exist or is used for an
709 @retval EFI_NOT_FOUND Free a non-using space or remove a non-exist
711 @retval EFI_OUT_OF_RESOURCES No buffer could be allocated.
712 @retval EFI_NOT_AVAILABLE_YET The attributes cannot be set because CPU architectural protocol
713 is not available yet.
718 IN EFI_GCD_MEMORY_TYPE GcdMemoryType
,
719 IN EFI_GCD_IO_TYPE GcdIoType
,
720 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
722 IN UINT64 Capabilities
,
729 EFI_GCD_MAP_ENTRY
*Entry
;
730 EFI_GCD_MAP_ENTRY
*TopEntry
;
731 EFI_GCD_MAP_ENTRY
*BottomEntry
;
732 LIST_ENTRY
*StartLink
;
734 UINT64 CpuArchAttributes
;
737 DEBUG ((DEBUG_GCD
, " Status = %r\n", EFI_INVALID_PARAMETER
));
738 return EFI_INVALID_PARAMETER
;
742 if ((Operation
& GCD_MEMORY_SPACE_OPERATION
) != 0) {
743 CoreAcquireGcdMemoryLock ();
744 Map
= &mGcdMemorySpaceMap
;
745 } else if ((Operation
& GCD_IO_SPACE_OPERATION
) != 0) {
746 CoreAcquireGcdIoLock ();
747 Map
= &mGcdIoSpaceMap
;
753 // Search for the list of descriptors that cover the range BaseAddress to BaseAddress+Length
755 Status
= CoreSearchGcdMapEntry (BaseAddress
, Length
, &StartLink
, &EndLink
, Map
);
756 if (EFI_ERROR (Status
)) {
757 Status
= EFI_UNSUPPORTED
;
761 ASSERT (StartLink
!= NULL
&& EndLink
!= NULL
);
764 // Verify that the list of descriptors are unallocated non-existent memory.
767 while (Link
!= EndLink
->ForwardLink
) {
768 Entry
= CR (Link
, EFI_GCD_MAP_ENTRY
, Link
, EFI_GCD_MAP_SIGNATURE
);
773 case GCD_ADD_MEMORY_OPERATION
:
774 if (Entry
->GcdMemoryType
!= EfiGcdMemoryTypeNonExistent
||
775 Entry
->ImageHandle
!= NULL
) {
776 Status
= EFI_ACCESS_DENIED
;
780 case GCD_ADD_IO_OPERATION
:
781 if (Entry
->GcdIoType
!= EfiGcdIoTypeNonExistent
||
782 Entry
->ImageHandle
!= NULL
) {
783 Status
= EFI_ACCESS_DENIED
;
790 case GCD_FREE_MEMORY_OPERATION
:
791 case GCD_FREE_IO_OPERATION
:
792 if (Entry
->ImageHandle
== NULL
) {
793 Status
= EFI_NOT_FOUND
;
800 case GCD_REMOVE_MEMORY_OPERATION
:
801 if (Entry
->GcdMemoryType
== EfiGcdMemoryTypeNonExistent
) {
802 Status
= EFI_NOT_FOUND
;
805 if (Entry
->ImageHandle
!= NULL
) {
806 Status
= EFI_ACCESS_DENIED
;
810 case GCD_REMOVE_IO_OPERATION
:
811 if (Entry
->GcdIoType
== EfiGcdIoTypeNonExistent
) {
812 Status
= EFI_NOT_FOUND
;
815 if (Entry
->ImageHandle
!= NULL
) {
816 Status
= EFI_ACCESS_DENIED
;
821 // Set attributes operation
823 case GCD_SET_ATTRIBUTES_MEMORY_OPERATION
:
824 if ((Attributes
& EFI_MEMORY_RUNTIME
) != 0) {
825 if ((BaseAddress
& EFI_PAGE_MASK
) != 0 || (Length
& EFI_PAGE_MASK
) != 0) {
826 Status
= EFI_INVALID_PARAMETER
;
830 if ((Entry
->Capabilities
& Attributes
) != Attributes
) {
831 Status
= EFI_UNSUPPORTED
;
836 // Set capabilities operation
838 case GCD_SET_CAPABILITIES_MEMORY_OPERATION
:
839 if ((BaseAddress
& EFI_PAGE_MASK
) != 0 || (Length
& EFI_PAGE_MASK
) != 0) {
840 Status
= EFI_INVALID_PARAMETER
;
845 // Current attributes must still be supported with new capabilities
847 if ((Capabilities
& Entry
->Attributes
) != Entry
->Attributes
) {
848 Status
= EFI_UNSUPPORTED
;
853 Link
= Link
->ForwardLink
;
857 // Allocate work space to perform this operation
859 Status
= CoreAllocateGcdMapEntry (&TopEntry
, &BottomEntry
);
860 if (EFI_ERROR (Status
)) {
861 Status
= EFI_OUT_OF_RESOURCES
;
864 ASSERT (TopEntry
!= NULL
&& BottomEntry
!= NULL
);
866 if (Operation
== GCD_SET_ATTRIBUTES_MEMORY_OPERATION
) {
868 // Call CPU Arch Protocol to attempt to set attributes on the range
870 CpuArchAttributes
= ConverToCpuArchAttributes (Attributes
);
871 if (CpuArchAttributes
!= INVALID_CPU_ARCH_ATTRIBUTES
) {
873 Status
= EFI_NOT_AVAILABLE_YET
;
875 Status
= gCpu
->SetMemoryAttributes (
882 if (EFI_ERROR (Status
)) {
883 CoreFreePool (TopEntry
);
884 CoreFreePool (BottomEntry
);
891 // Convert/Insert the list of descriptors from StartLink to EndLink
894 while (Link
!= EndLink
->ForwardLink
) {
895 Entry
= CR (Link
, EFI_GCD_MAP_ENTRY
, Link
, EFI_GCD_MAP_SIGNATURE
);
896 CoreInsertGcdMapEntry (Link
, Entry
, BaseAddress
, Length
, TopEntry
, BottomEntry
);
901 case GCD_ADD_MEMORY_OPERATION
:
902 Entry
->GcdMemoryType
= GcdMemoryType
;
903 if (GcdMemoryType
== EfiGcdMemoryTypeMemoryMappedIo
) {
904 Entry
->Capabilities
= Capabilities
| EFI_MEMORY_RUNTIME
| EFI_MEMORY_PORT_IO
;
906 Entry
->Capabilities
= Capabilities
| EFI_MEMORY_RUNTIME
;
909 case GCD_ADD_IO_OPERATION
:
910 Entry
->GcdIoType
= GcdIoType
;
915 case GCD_FREE_MEMORY_OPERATION
:
916 case GCD_FREE_IO_OPERATION
:
917 Entry
->ImageHandle
= NULL
;
918 Entry
->DeviceHandle
= NULL
;
923 case GCD_REMOVE_MEMORY_OPERATION
:
924 Entry
->GcdMemoryType
= EfiGcdMemoryTypeNonExistent
;
925 Entry
->Capabilities
= 0;
927 case GCD_REMOVE_IO_OPERATION
:
928 Entry
->GcdIoType
= EfiGcdIoTypeNonExistent
;
931 // Set attributes operation
933 case GCD_SET_ATTRIBUTES_MEMORY_OPERATION
:
934 Entry
->Attributes
= Attributes
;
937 // Set capabilities operation
939 case GCD_SET_CAPABILITIES_MEMORY_OPERATION
:
940 Entry
->Capabilities
= Capabilities
;
943 Link
= Link
->ForwardLink
;
949 Status
= CoreCleanupGcdMapEntry (TopEntry
, BottomEntry
, StartLink
, EndLink
, Map
);
952 DEBUG ((DEBUG_GCD
, " Status = %r\n", Status
));
954 if ((Operation
& GCD_MEMORY_SPACE_OPERATION
) != 0) {
955 CoreReleaseGcdMemoryLock ();
956 CoreDumpGcdMemorySpaceMap (FALSE
);
958 if ((Operation
& GCD_IO_SPACE_OPERATION
) != 0) {
959 CoreReleaseGcdIoLock ();
960 CoreDumpGcdIoSpaceMap (FALSE
);
968 Check whether an entry could be used to allocate space.
970 @param Operation Allocate memory or IO
971 @param Entry The entry to be tested
972 @param GcdMemoryType The desired memory type
973 @param GcdIoType The desired IO type
975 @retval EFI_NOT_FOUND The memory type does not match or there's an
976 image handle on the entry.
977 @retval EFI_UNSUPPORTED The operation unsupported.
978 @retval EFI_SUCCESS It's ok for this entry to be used to allocate
983 CoreAllocateSpaceCheckEntry (
985 IN EFI_GCD_MAP_ENTRY
*Entry
,
986 IN EFI_GCD_MEMORY_TYPE GcdMemoryType
,
987 IN EFI_GCD_IO_TYPE GcdIoType
990 if (Entry
->ImageHandle
!= NULL
) {
991 return EFI_NOT_FOUND
;
994 case GCD_ALLOCATE_MEMORY_OPERATION
:
995 if (Entry
->GcdMemoryType
!= GcdMemoryType
) {
996 return EFI_NOT_FOUND
;
999 case GCD_ALLOCATE_IO_OPERATION
:
1000 if (Entry
->GcdIoType
!= GcdIoType
) {
1001 return EFI_NOT_FOUND
;
1005 return EFI_UNSUPPORTED
;
1012 Allocate space on specified address and length.
1014 @param Operation The type of operation (memory or IO)
1015 @param GcdAllocateType The type of allocate operation
1016 @param GcdMemoryType The desired memory type
1017 @param GcdIoType The desired IO type
1018 @param Alignment Align with 2^Alignment
1019 @param Length Length to allocate
1020 @param BaseAddress Base address to allocate
1021 @param ImageHandle The image handle consume the allocated space.
1022 @param DeviceHandle The device handle consume the allocated space.
1024 @retval EFI_INVALID_PARAMETER Invalid parameter.
1025 @retval EFI_NOT_FOUND No descriptor for the desired space exists.
1026 @retval EFI_SUCCESS Space successfully allocated.
1032 IN EFI_GCD_ALLOCATE_TYPE GcdAllocateType
,
1033 IN EFI_GCD_MEMORY_TYPE GcdMemoryType
,
1034 IN EFI_GCD_IO_TYPE GcdIoType
,
1037 IN OUT EFI_PHYSICAL_ADDRESS
*BaseAddress
,
1038 IN EFI_HANDLE ImageHandle
,
1039 IN EFI_HANDLE DeviceHandle OPTIONAL
1043 EFI_PHYSICAL_ADDRESS AlignmentMask
;
1044 EFI_PHYSICAL_ADDRESS MaxAddress
;
1047 LIST_ENTRY
*SubLink
;
1048 EFI_GCD_MAP_ENTRY
*Entry
;
1049 EFI_GCD_MAP_ENTRY
*TopEntry
;
1050 EFI_GCD_MAP_ENTRY
*BottomEntry
;
1051 LIST_ENTRY
*StartLink
;
1052 LIST_ENTRY
*EndLink
;
1056 // Make sure parameters are valid
1058 if ((UINT32
)GcdAllocateType
>= EfiGcdMaxAllocateType
) {
1059 DEBUG ((DEBUG_GCD
, " Status = %r\n", EFI_INVALID_PARAMETER
));
1060 return EFI_INVALID_PARAMETER
;
1062 if ((UINT32
)GcdMemoryType
>= EfiGcdMemoryTypeMaximum
) {
1063 DEBUG ((DEBUG_GCD
, " Status = %r\n", EFI_INVALID_PARAMETER
));
1064 return EFI_INVALID_PARAMETER
;
1066 if ((UINT32
)GcdIoType
>= EfiGcdIoTypeMaximum
) {
1067 DEBUG ((DEBUG_GCD
, " Status = %r\n", EFI_INVALID_PARAMETER
));
1068 return EFI_INVALID_PARAMETER
;
1070 if (BaseAddress
== NULL
) {
1071 DEBUG ((DEBUG_GCD
, " Status = %r\n", EFI_INVALID_PARAMETER
));
1072 return EFI_INVALID_PARAMETER
;
1074 if (ImageHandle
== NULL
) {
1075 DEBUG ((DEBUG_GCD
, " Status = %r\n", EFI_INVALID_PARAMETER
));
1076 return EFI_INVALID_PARAMETER
;
1078 if (Alignment
>= 64) {
1079 DEBUG ((DEBUG_GCD
, " Status = %r\n", EFI_NOT_FOUND
));
1080 return EFI_NOT_FOUND
;
1083 DEBUG ((DEBUG_GCD
, " Status = %r\n", EFI_INVALID_PARAMETER
));
1084 return EFI_INVALID_PARAMETER
;
1088 if ((Operation
& GCD_MEMORY_SPACE_OPERATION
) != 0) {
1089 CoreAcquireGcdMemoryLock ();
1090 Map
= &mGcdMemorySpaceMap
;
1091 } else if ((Operation
& GCD_IO_SPACE_OPERATION
) != 0) {
1092 CoreAcquireGcdIoLock ();
1093 Map
= &mGcdIoSpaceMap
;
1102 // Compute alignment bit mask
1104 AlignmentMask
= LShiftU64 (1, Alignment
) - 1;
1106 if (GcdAllocateType
== EfiGcdAllocateAddress
) {
1108 // Verify that the BaseAddress passed in is aligned correctly
1110 if ((*BaseAddress
& AlignmentMask
) != 0) {
1111 Status
= EFI_NOT_FOUND
;
1116 // Search for the list of descriptors that cover the range BaseAddress to BaseAddress+Length
1118 Status
= CoreSearchGcdMapEntry (*BaseAddress
, Length
, &StartLink
, &EndLink
, Map
);
1119 if (EFI_ERROR (Status
)) {
1120 Status
= EFI_NOT_FOUND
;
1123 ASSERT (StartLink
!= NULL
&& EndLink
!= NULL
);
1126 // Verify that the list of descriptors are unallocated memory matching GcdMemoryType.
1129 while (Link
!= EndLink
->ForwardLink
) {
1130 Entry
= CR (Link
, EFI_GCD_MAP_ENTRY
, Link
, EFI_GCD_MAP_SIGNATURE
);
1131 Link
= Link
->ForwardLink
;
1132 Status
= CoreAllocateSpaceCheckEntry (Operation
, Entry
, GcdMemoryType
, GcdIoType
);
1133 if (EFI_ERROR (Status
)) {
1140 Entry
= CR (Map
->BackLink
, EFI_GCD_MAP_ENTRY
, Link
, EFI_GCD_MAP_SIGNATURE
);
1143 // Compute the maximum address to use in the search algorithm
1145 if (GcdAllocateType
== EfiGcdAllocateMaxAddressSearchBottomUp
||
1146 GcdAllocateType
== EfiGcdAllocateMaxAddressSearchTopDown
) {
1147 MaxAddress
= *BaseAddress
;
1149 MaxAddress
= Entry
->EndAddress
;
1153 // Verify that the list of descriptors are unallocated memory matching GcdMemoryType.
1155 if (GcdAllocateType
== EfiGcdAllocateMaxAddressSearchTopDown
||
1156 GcdAllocateType
== EfiGcdAllocateAnySearchTopDown
) {
1157 Link
= Map
->BackLink
;
1159 Link
= Map
->ForwardLink
;
1161 while (Link
!= Map
) {
1162 Entry
= CR (Link
, EFI_GCD_MAP_ENTRY
, Link
, EFI_GCD_MAP_SIGNATURE
);
1164 if (GcdAllocateType
== EfiGcdAllocateMaxAddressSearchTopDown
||
1165 GcdAllocateType
== EfiGcdAllocateAnySearchTopDown
) {
1166 Link
= Link
->BackLink
;
1168 Link
= Link
->ForwardLink
;
1171 Status
= CoreAllocateSpaceCheckEntry (Operation
, Entry
, GcdMemoryType
, GcdIoType
);
1172 if (EFI_ERROR (Status
)) {
1176 if (GcdAllocateType
== EfiGcdAllocateMaxAddressSearchTopDown
||
1177 GcdAllocateType
== EfiGcdAllocateAnySearchTopDown
) {
1178 if ((Entry
->BaseAddress
+ Length
) > MaxAddress
) {
1181 if (Length
> (Entry
->EndAddress
+ 1)) {
1182 Status
= EFI_NOT_FOUND
;
1185 if (Entry
->EndAddress
> MaxAddress
) {
1186 *BaseAddress
= MaxAddress
;
1188 *BaseAddress
= Entry
->EndAddress
;
1190 *BaseAddress
= (*BaseAddress
+ 1 - Length
) & (~AlignmentMask
);
1192 *BaseAddress
= (Entry
->BaseAddress
+ AlignmentMask
) & (~AlignmentMask
);
1193 if ((*BaseAddress
+ Length
- 1) > MaxAddress
) {
1194 Status
= EFI_NOT_FOUND
;
1200 // Search for the list of descriptors that cover the range BaseAddress to BaseAddress+Length
1202 Status
= CoreSearchGcdMapEntry (*BaseAddress
, Length
, &StartLink
, &EndLink
, Map
);
1203 if (EFI_ERROR (Status
)) {
1204 Status
= EFI_NOT_FOUND
;
1207 ASSERT (StartLink
!= NULL
&& EndLink
!= NULL
);
1211 // Verify that the list of descriptors are unallocated memory matching GcdMemoryType.
1214 SubLink
= StartLink
;
1215 while (SubLink
!= EndLink
->ForwardLink
) {
1216 Entry
= CR (SubLink
, EFI_GCD_MAP_ENTRY
, Link
, EFI_GCD_MAP_SIGNATURE
);
1217 Status
= CoreAllocateSpaceCheckEntry (Operation
, Entry
, GcdMemoryType
, GcdIoType
);
1218 if (EFI_ERROR (Status
)) {
1223 SubLink
= SubLink
->ForwardLink
;
1231 Status
= EFI_NOT_FOUND
;
1236 // Allocate work space to perform this operation
1238 Status
= CoreAllocateGcdMapEntry (&TopEntry
, &BottomEntry
);
1239 if (EFI_ERROR (Status
)) {
1240 Status
= EFI_OUT_OF_RESOURCES
;
1243 ASSERT (TopEntry
!= NULL
&& BottomEntry
!= NULL
);
1246 // Convert/Insert the list of descriptors from StartLink to EndLink
1249 while (Link
!= EndLink
->ForwardLink
) {
1250 Entry
= CR (Link
, EFI_GCD_MAP_ENTRY
, Link
, EFI_GCD_MAP_SIGNATURE
);
1251 CoreInsertGcdMapEntry (Link
, Entry
, *BaseAddress
, Length
, TopEntry
, BottomEntry
);
1252 Entry
->ImageHandle
= ImageHandle
;
1253 Entry
->DeviceHandle
= DeviceHandle
;
1254 Link
= Link
->ForwardLink
;
1260 Status
= CoreCleanupGcdMapEntry (TopEntry
, BottomEntry
, StartLink
, EndLink
, Map
);
1263 DEBUG ((DEBUG_GCD
, " Status = %r", Status
));
1264 if (!EFI_ERROR (Status
)) {
1265 DEBUG ((DEBUG_GCD
, " (BaseAddress = %016lx)", *BaseAddress
));
1267 DEBUG ((DEBUG_GCD
, "\n"));
1269 if ((Operation
& GCD_MEMORY_SPACE_OPERATION
) != 0) {
1270 CoreReleaseGcdMemoryLock ();
1271 CoreDumpGcdMemorySpaceMap (FALSE
);
1273 if ((Operation
& GCD_IO_SPACE_OPERATION
) !=0) {
1274 CoreReleaseGcdIoLock ();
1275 CoreDumpGcdIoSpaceMap (FALSE
);
1283 Add a segment of memory to GCD map.
1285 @param GcdMemoryType Memory type of the segment.
1286 @param BaseAddress Base address of the segment.
1287 @param Length Length of the segment.
1288 @param Capabilities alterable attributes of the segment.
1290 @retval EFI_INVALID_PARAMETER Invalid parameters.
1291 @retval EFI_SUCCESS Successfully add a segment of memory space.
1295 CoreInternalAddMemorySpace (
1296 IN EFI_GCD_MEMORY_TYPE GcdMemoryType
,
1297 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
1299 IN UINT64 Capabilities
1302 DEBUG ((DEBUG_GCD
, "GCD:AddMemorySpace(Base=%016lx,Length=%016lx)\n", BaseAddress
, Length
));
1303 DEBUG ((DEBUG_GCD
, " GcdMemoryType = %a\n", mGcdMemoryTypeNames
[MIN (GcdMemoryType
, EfiGcdMemoryTypeMaximum
)]));
1304 DEBUG ((DEBUG_GCD
, " Capabilities = %016lx\n", Capabilities
));
1307 // Make sure parameters are valid
1309 if (GcdMemoryType
<= EfiGcdMemoryTypeNonExistent
|| GcdMemoryType
>= EfiGcdMemoryTypeMaximum
) {
1310 return EFI_INVALID_PARAMETER
;
1313 return CoreConvertSpace (GCD_ADD_MEMORY_OPERATION
, GcdMemoryType
, (EFI_GCD_IO_TYPE
) 0, BaseAddress
, Length
, Capabilities
, 0);
1317 // GCD Core Services
1321 Allocates nonexistent memory, reserved memory, system memory, or memorymapped
1322 I/O resources from the global coherency domain of the processor.
1324 @param GcdAllocateType The type of allocate operation
1325 @param GcdMemoryType The desired memory type
1326 @param Alignment Align with 2^Alignment
1327 @param Length Length to allocate
1328 @param BaseAddress Base address to allocate
1329 @param ImageHandle The image handle consume the allocated space.
1330 @param DeviceHandle The device handle consume the allocated space.
1332 @retval EFI_INVALID_PARAMETER Invalid parameter.
1333 @retval EFI_NOT_FOUND No descriptor contains the desired space.
1334 @retval EFI_SUCCESS Memory space successfully allocated.
1339 CoreAllocateMemorySpace (
1340 IN EFI_GCD_ALLOCATE_TYPE GcdAllocateType
,
1341 IN EFI_GCD_MEMORY_TYPE GcdMemoryType
,
1344 IN OUT EFI_PHYSICAL_ADDRESS
*BaseAddress
,
1345 IN EFI_HANDLE ImageHandle
,
1346 IN EFI_HANDLE DeviceHandle OPTIONAL
1349 if (BaseAddress
!= NULL
) {
1350 DEBUG ((DEBUG_GCD
, "GCD:AllocateMemorySpace(Base=%016lx,Length=%016lx)\n", *BaseAddress
, Length
));
1352 DEBUG ((DEBUG_GCD
, "GCD:AllocateMemorySpace(Base=<NULL>,Length=%016lx)\n", Length
));
1354 DEBUG ((DEBUG_GCD
, " GcdAllocateType = %a\n", mGcdAllocationTypeNames
[MIN (GcdAllocateType
, EfiGcdMaxAllocateType
)]));
1355 DEBUG ((DEBUG_GCD
, " GcdMemoryType = %a\n", mGcdMemoryTypeNames
[MIN (GcdMemoryType
, EfiGcdMemoryTypeMaximum
)]));
1356 DEBUG ((DEBUG_GCD
, " Alignment = %016lx\n", LShiftU64 (1, Alignment
)));
1357 DEBUG ((DEBUG_GCD
, " ImageHandle = %p\n", ImageHandle
));
1358 DEBUG ((DEBUG_GCD
, " DeviceHandle = %p\n", DeviceHandle
));
1360 return CoreAllocateSpace (
1361 GCD_ALLOCATE_MEMORY_OPERATION
,
1364 (EFI_GCD_IO_TYPE
) 0,
1375 Adds reserved memory, system memory, or memory-mapped I/O resources to the
1376 global coherency domain of the processor.
1378 @param GcdMemoryType Memory type of the memory space.
1379 @param BaseAddress Base address of the memory space.
1380 @param Length Length of the memory space.
1381 @param Capabilities alterable attributes of the memory space.
1383 @retval EFI_SUCCESS Merged this memory space into GCD map.
1388 CoreAddMemorySpace (
1389 IN EFI_GCD_MEMORY_TYPE GcdMemoryType
,
1390 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
1392 IN UINT64 Capabilities
1396 EFI_PHYSICAL_ADDRESS PageBaseAddress
;
1399 Status
= CoreInternalAddMemorySpace (GcdMemoryType
, BaseAddress
, Length
, Capabilities
);
1401 if (!EFI_ERROR (Status
) && ((GcdMemoryType
== EfiGcdMemoryTypeSystemMemory
) || (GcdMemoryType
== EfiGcdMemoryTypeMoreReliable
))) {
1403 PageBaseAddress
= PageAlignAddress (BaseAddress
);
1404 PageLength
= PageAlignLength (BaseAddress
+ Length
- PageBaseAddress
);
1406 Status
= CoreAllocateMemorySpace (
1407 EfiGcdAllocateAddress
,
1412 gDxeCoreImageHandle
,
1416 if (!EFI_ERROR (Status
)) {
1417 CoreAddMemoryDescriptor (
1418 EfiConventionalMemory
,
1420 RShiftU64 (PageLength
, EFI_PAGE_SHIFT
),
1424 for (; PageLength
!= 0; PageLength
-= EFI_PAGE_SIZE
, PageBaseAddress
+= EFI_PAGE_SIZE
) {
1425 Status
= CoreAllocateMemorySpace (
1426 EfiGcdAllocateAddress
,
1431 gDxeCoreImageHandle
,
1435 if (!EFI_ERROR (Status
)) {
1436 CoreAddMemoryDescriptor (
1437 EfiConventionalMemory
,
1451 Frees nonexistent memory, reserved memory, system memory, or memory-mapped
1452 I/O resources from the global coherency domain of the processor.
1454 @param BaseAddress Base address of the memory space.
1455 @param Length Length of the memory space.
1457 @retval EFI_SUCCESS Space successfully freed.
1462 CoreFreeMemorySpace (
1463 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
1467 DEBUG ((DEBUG_GCD
, "GCD:FreeMemorySpace(Base=%016lx,Length=%016lx)\n", BaseAddress
, Length
));
1469 return CoreConvertSpace (GCD_FREE_MEMORY_OPERATION
, (EFI_GCD_MEMORY_TYPE
) 0, (EFI_GCD_IO_TYPE
) 0, BaseAddress
, Length
, 0, 0);
1474 Removes reserved memory, system memory, or memory-mapped I/O resources from
1475 the global coherency domain of the processor.
1477 @param BaseAddress Base address of the memory space.
1478 @param Length Length of the memory space.
1480 @retval EFI_SUCCESS Successfully remove a segment of memory space.
1485 CoreRemoveMemorySpace (
1486 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
1490 DEBUG ((DEBUG_GCD
, "GCD:RemoveMemorySpace(Base=%016lx,Length=%016lx)\n", BaseAddress
, Length
));
1492 return CoreConvertSpace (GCD_REMOVE_MEMORY_OPERATION
, (EFI_GCD_MEMORY_TYPE
) 0, (EFI_GCD_IO_TYPE
) 0, BaseAddress
, Length
, 0, 0);
1497 Build a memory descriptor according to an entry.
1499 @param Descriptor The descriptor to be built
1500 @param Entry According to this entry
1504 BuildMemoryDescriptor (
1505 IN OUT EFI_GCD_MEMORY_SPACE_DESCRIPTOR
*Descriptor
,
1506 IN EFI_GCD_MAP_ENTRY
*Entry
1509 Descriptor
->BaseAddress
= Entry
->BaseAddress
;
1510 Descriptor
->Length
= Entry
->EndAddress
- Entry
->BaseAddress
+ 1;
1511 Descriptor
->Capabilities
= Entry
->Capabilities
;
1512 Descriptor
->Attributes
= Entry
->Attributes
;
1513 Descriptor
->GcdMemoryType
= Entry
->GcdMemoryType
;
1514 Descriptor
->ImageHandle
= Entry
->ImageHandle
;
1515 Descriptor
->DeviceHandle
= Entry
->DeviceHandle
;
1520 Retrieves the descriptor for a memory region containing a specified address.
1522 @param BaseAddress Specified start address
1523 @param Descriptor Specified length
1525 @retval EFI_INVALID_PARAMETER Invalid parameter
1526 @retval EFI_SUCCESS Successfully get memory space descriptor.
1531 CoreGetMemorySpaceDescriptor (
1532 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
1533 OUT EFI_GCD_MEMORY_SPACE_DESCRIPTOR
*Descriptor
1537 LIST_ENTRY
*StartLink
;
1538 LIST_ENTRY
*EndLink
;
1539 EFI_GCD_MAP_ENTRY
*Entry
;
1542 // Make sure parameters are valid
1544 if (Descriptor
== NULL
) {
1545 return EFI_INVALID_PARAMETER
;
1548 CoreAcquireGcdMemoryLock ();
1551 // Search for the list of descriptors that contain BaseAddress
1553 Status
= CoreSearchGcdMapEntry (BaseAddress
, 1, &StartLink
, &EndLink
, &mGcdMemorySpaceMap
);
1554 if (EFI_ERROR (Status
)) {
1555 Status
= EFI_NOT_FOUND
;
1557 ASSERT (StartLink
!= NULL
&& EndLink
!= NULL
);
1559 // Copy the contents of the found descriptor into Descriptor
1561 Entry
= CR (StartLink
, EFI_GCD_MAP_ENTRY
, Link
, EFI_GCD_MAP_SIGNATURE
);
1562 BuildMemoryDescriptor (Descriptor
, Entry
);
1565 CoreReleaseGcdMemoryLock ();
1572 Modifies the attributes for a memory region in the global coherency domain of the
1575 @param BaseAddress Specified start address
1576 @param Length Specified length
1577 @param Attributes Specified attributes
1579 @retval EFI_SUCCESS The attributes were set for the memory region.
1580 @retval EFI_INVALID_PARAMETER Length is zero.
1581 @retval EFI_UNSUPPORTED The processor does not support one or more bytes of the memory
1582 resource range specified by BaseAddress and Length.
1583 @retval EFI_UNSUPPORTED The bit mask of attributes is not support for the memory resource
1584 range specified by BaseAddress and Length.
1585 @retval EFI_ACCESS_DEFINED The attributes for the memory resource range specified by
1586 BaseAddress and Length cannot be modified.
1587 @retval EFI_OUT_OF_RESOURCES There are not enough system resources to modify the attributes of
1588 the memory resource range.
1589 @retval EFI_NOT_AVAILABLE_YET The attributes cannot be set because CPU architectural protocol is
1595 CoreSetMemorySpaceAttributes (
1596 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
1598 IN UINT64 Attributes
1601 DEBUG ((DEBUG_GCD
, "GCD:SetMemorySpaceAttributes(Base=%016lx,Length=%016lx)\n", BaseAddress
, Length
));
1602 DEBUG ((DEBUG_GCD
, " Attributes = %016lx\n", Attributes
));
1604 return CoreConvertSpace (GCD_SET_ATTRIBUTES_MEMORY_OPERATION
, (EFI_GCD_MEMORY_TYPE
) 0, (EFI_GCD_IO_TYPE
) 0, BaseAddress
, Length
, 0, Attributes
);
1609 Modifies the capabilities for a memory region in the global coherency domain of the
1612 @param BaseAddress The physical address that is the start address of a memory region.
1613 @param Length The size in bytes of the memory region.
1614 @param Capabilities The bit mask of capabilities that the memory region supports.
1616 @retval EFI_SUCCESS The capabilities were set for the memory region.
1617 @retval EFI_INVALID_PARAMETER Length is zero.
1618 @retval EFI_UNSUPPORTED The capabilities specified by Capabilities do not include the
1619 memory region attributes currently in use.
1620 @retval EFI_ACCESS_DENIED The capabilities for the memory resource range specified by
1621 BaseAddress and Length cannot be modified.
1622 @retval EFI_OUT_OF_RESOURCES There are not enough system resources to modify the capabilities
1623 of the memory resource range.
1627 CoreSetMemorySpaceCapabilities (
1628 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
1630 IN UINT64 Capabilities
1635 DEBUG ((DEBUG_GCD
, "GCD:CoreSetMemorySpaceCapabilities(Base=%016lx,Length=%016lx)\n", BaseAddress
, Length
));
1636 DEBUG ((DEBUG_GCD
, " Capabilities = %016lx\n", Capabilities
));
1638 Status
= CoreConvertSpace (GCD_SET_CAPABILITIES_MEMORY_OPERATION
, (EFI_GCD_MEMORY_TYPE
) 0, (EFI_GCD_IO_TYPE
) 0, BaseAddress
, Length
, Capabilities
, 0);
1639 if (!EFI_ERROR(Status
)) {
1640 CoreUpdateMemoryAttributes(BaseAddress
, RShiftU64(Length
, EFI_PAGE_SHIFT
), Capabilities
& (~EFI_MEMORY_RUNTIME
));
1648 Returns a map of the memory resources in the global coherency domain of the
1651 @param NumberOfDescriptors Number of descriptors.
1652 @param MemorySpaceMap Descriptor array
1654 @retval EFI_INVALID_PARAMETER Invalid parameter
1655 @retval EFI_OUT_OF_RESOURCES No enough buffer to allocate
1656 @retval EFI_SUCCESS Successfully get memory space map.
1661 CoreGetMemorySpaceMap (
1662 OUT UINTN
*NumberOfDescriptors
,
1663 OUT EFI_GCD_MEMORY_SPACE_DESCRIPTOR
**MemorySpaceMap
1668 EFI_GCD_MAP_ENTRY
*Entry
;
1669 EFI_GCD_MEMORY_SPACE_DESCRIPTOR
*Descriptor
;
1672 // Make sure parameters are valid
1674 if (NumberOfDescriptors
== NULL
) {
1675 return EFI_INVALID_PARAMETER
;
1677 if (MemorySpaceMap
== NULL
) {
1678 return EFI_INVALID_PARAMETER
;
1681 CoreAcquireGcdMemoryLock ();
1684 // Count the number of descriptors
1686 *NumberOfDescriptors
= CoreCountGcdMapEntry (&mGcdMemorySpaceMap
);
1689 // Allocate the MemorySpaceMap
1691 *MemorySpaceMap
= AllocatePool (*NumberOfDescriptors
* sizeof (EFI_GCD_MEMORY_SPACE_DESCRIPTOR
));
1692 if (*MemorySpaceMap
== NULL
) {
1693 Status
= EFI_OUT_OF_RESOURCES
;
1698 // Fill in the MemorySpaceMap
1700 Descriptor
= *MemorySpaceMap
;
1701 Link
= mGcdMemorySpaceMap
.ForwardLink
;
1702 while (Link
!= &mGcdMemorySpaceMap
) {
1703 Entry
= CR (Link
, EFI_GCD_MAP_ENTRY
, Link
, EFI_GCD_MAP_SIGNATURE
);
1704 BuildMemoryDescriptor (Descriptor
, Entry
);
1706 Link
= Link
->ForwardLink
;
1708 Status
= EFI_SUCCESS
;
1711 CoreReleaseGcdMemoryLock ();
1717 Adds reserved I/O or I/O resources to the global coherency domain of the processor.
1719 @param GcdIoType IO type of the segment.
1720 @param BaseAddress Base address of the segment.
1721 @param Length Length of the segment.
1723 @retval EFI_SUCCESS Merged this segment into GCD map.
1724 @retval EFI_INVALID_PARAMETER Parameter not valid
1730 IN EFI_GCD_IO_TYPE GcdIoType
,
1731 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
1735 DEBUG ((DEBUG_GCD
, "GCD:AddIoSpace(Base=%016lx,Length=%016lx)\n", BaseAddress
, Length
));
1736 DEBUG ((DEBUG_GCD
, " GcdIoType = %a\n", mGcdIoTypeNames
[MIN (GcdIoType
, EfiGcdIoTypeMaximum
)]));
1739 // Make sure parameters are valid
1741 if (GcdIoType
<= EfiGcdIoTypeNonExistent
|| GcdIoType
>= EfiGcdIoTypeMaximum
) {
1742 return EFI_INVALID_PARAMETER
;
1744 return CoreConvertSpace (GCD_ADD_IO_OPERATION
, (EFI_GCD_MEMORY_TYPE
) 0, GcdIoType
, BaseAddress
, Length
, 0, 0);
1749 Allocates nonexistent I/O, reserved I/O, or I/O resources from the global coherency
1750 domain of the processor.
1752 @param GcdAllocateType The type of allocate operation
1753 @param GcdIoType The desired IO type
1754 @param Alignment Align with 2^Alignment
1755 @param Length Length to allocate
1756 @param BaseAddress Base address to allocate
1757 @param ImageHandle The image handle consume the allocated space.
1758 @param DeviceHandle The device handle consume the allocated space.
1760 @retval EFI_INVALID_PARAMETER Invalid parameter.
1761 @retval EFI_NOT_FOUND No descriptor contains the desired space.
1762 @retval EFI_SUCCESS IO space successfully allocated.
1767 CoreAllocateIoSpace (
1768 IN EFI_GCD_ALLOCATE_TYPE GcdAllocateType
,
1769 IN EFI_GCD_IO_TYPE GcdIoType
,
1772 IN OUT EFI_PHYSICAL_ADDRESS
*BaseAddress
,
1773 IN EFI_HANDLE ImageHandle
,
1774 IN EFI_HANDLE DeviceHandle OPTIONAL
1777 if (BaseAddress
!= NULL
) {
1778 DEBUG ((DEBUG_GCD
, "GCD:AllocateIoSpace(Base=%016lx,Length=%016lx)\n", *BaseAddress
, Length
));
1780 DEBUG ((DEBUG_GCD
, "GCD:AllocateIoSpace(Base=<NULL>,Length=%016lx)\n", Length
));
1782 DEBUG ((DEBUG_GCD
, " GcdAllocateType = %a\n", mGcdAllocationTypeNames
[MIN (GcdAllocateType
, EfiGcdMaxAllocateType
)]));
1783 DEBUG ((DEBUG_GCD
, " GcdIoType = %a\n", mGcdIoTypeNames
[MIN (GcdIoType
, EfiGcdIoTypeMaximum
)]));
1784 DEBUG ((DEBUG_GCD
, " Alignment = %016lx\n", LShiftU64 (1, Alignment
)));
1785 DEBUG ((DEBUG_GCD
, " ImageHandle = %p\n", ImageHandle
));
1786 DEBUG ((DEBUG_GCD
, " DeviceHandle = %p\n", DeviceHandle
));
1788 return CoreAllocateSpace (
1789 GCD_ALLOCATE_IO_OPERATION
,
1791 (EFI_GCD_MEMORY_TYPE
) 0,
1803 Frees nonexistent I/O, reserved I/O, or I/O resources from the global coherency
1804 domain of the processor.
1806 @param BaseAddress Base address of the segment.
1807 @param Length Length of the segment.
1809 @retval EFI_SUCCESS Space successfully freed.
1815 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
1819 DEBUG ((DEBUG_GCD
, "GCD:FreeIoSpace(Base=%016lx,Length=%016lx)\n", BaseAddress
, Length
));
1821 return CoreConvertSpace (GCD_FREE_IO_OPERATION
, (EFI_GCD_MEMORY_TYPE
) 0, (EFI_GCD_IO_TYPE
) 0, BaseAddress
, Length
, 0, 0);
1826 Removes reserved I/O or I/O resources from the global coherency domain of the
1829 @param BaseAddress Base address of the segment.
1830 @param Length Length of the segment.
1832 @retval EFI_SUCCESS Successfully removed a segment of IO space.
1838 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
1842 DEBUG ((DEBUG_GCD
, "GCD:RemoveIoSpace(Base=%016lx,Length=%016lx)\n", BaseAddress
, Length
));
1844 return CoreConvertSpace (GCD_REMOVE_IO_OPERATION
, (EFI_GCD_MEMORY_TYPE
) 0, (EFI_GCD_IO_TYPE
) 0, BaseAddress
, Length
, 0, 0);
1849 Build a IO descriptor according to an entry.
1851 @param Descriptor The descriptor to be built
1852 @param Entry According to this entry
1857 IN EFI_GCD_IO_SPACE_DESCRIPTOR
*Descriptor
,
1858 IN EFI_GCD_MAP_ENTRY
*Entry
1861 Descriptor
->BaseAddress
= Entry
->BaseAddress
;
1862 Descriptor
->Length
= Entry
->EndAddress
- Entry
->BaseAddress
+ 1;
1863 Descriptor
->GcdIoType
= Entry
->GcdIoType
;
1864 Descriptor
->ImageHandle
= Entry
->ImageHandle
;
1865 Descriptor
->DeviceHandle
= Entry
->DeviceHandle
;
1870 Retrieves the descriptor for an I/O region containing a specified address.
1872 @param BaseAddress Specified start address
1873 @param Descriptor Specified length
1875 @retval EFI_INVALID_PARAMETER Descriptor is NULL.
1876 @retval EFI_SUCCESS Successfully get the IO space descriptor.
1881 CoreGetIoSpaceDescriptor (
1882 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
1883 OUT EFI_GCD_IO_SPACE_DESCRIPTOR
*Descriptor
1887 LIST_ENTRY
*StartLink
;
1888 LIST_ENTRY
*EndLink
;
1889 EFI_GCD_MAP_ENTRY
*Entry
;
1892 // Make sure parameters are valid
1894 if (Descriptor
== NULL
) {
1895 return EFI_INVALID_PARAMETER
;
1898 CoreAcquireGcdIoLock ();
1901 // Search for the list of descriptors that contain BaseAddress
1903 Status
= CoreSearchGcdMapEntry (BaseAddress
, 1, &StartLink
, &EndLink
, &mGcdIoSpaceMap
);
1904 if (EFI_ERROR (Status
)) {
1905 Status
= EFI_NOT_FOUND
;
1907 ASSERT (StartLink
!= NULL
&& EndLink
!= NULL
);
1909 // Copy the contents of the found descriptor into Descriptor
1911 Entry
= CR (StartLink
, EFI_GCD_MAP_ENTRY
, Link
, EFI_GCD_MAP_SIGNATURE
);
1912 BuildIoDescriptor (Descriptor
, Entry
);
1915 CoreReleaseGcdIoLock ();
1922 Returns a map of the I/O resources in the global coherency domain of the processor.
1924 @param NumberOfDescriptors Number of descriptors.
1925 @param IoSpaceMap Descriptor array
1927 @retval EFI_INVALID_PARAMETER Invalid parameter
1928 @retval EFI_OUT_OF_RESOURCES No enough buffer to allocate
1929 @retval EFI_SUCCESS Successfully get IO space map.
1935 OUT UINTN
*NumberOfDescriptors
,
1936 OUT EFI_GCD_IO_SPACE_DESCRIPTOR
**IoSpaceMap
1941 EFI_GCD_MAP_ENTRY
*Entry
;
1942 EFI_GCD_IO_SPACE_DESCRIPTOR
*Descriptor
;
1945 // Make sure parameters are valid
1947 if (NumberOfDescriptors
== NULL
) {
1948 return EFI_INVALID_PARAMETER
;
1950 if (IoSpaceMap
== NULL
) {
1951 return EFI_INVALID_PARAMETER
;
1954 CoreAcquireGcdIoLock ();
1957 // Count the number of descriptors
1959 *NumberOfDescriptors
= CoreCountGcdMapEntry (&mGcdIoSpaceMap
);
1962 // Allocate the IoSpaceMap
1964 *IoSpaceMap
= AllocatePool (*NumberOfDescriptors
* sizeof (EFI_GCD_IO_SPACE_DESCRIPTOR
));
1965 if (*IoSpaceMap
== NULL
) {
1966 Status
= EFI_OUT_OF_RESOURCES
;
1971 // Fill in the IoSpaceMap
1973 Descriptor
= *IoSpaceMap
;
1974 Link
= mGcdIoSpaceMap
.ForwardLink
;
1975 while (Link
!= &mGcdIoSpaceMap
) {
1976 Entry
= CR (Link
, EFI_GCD_MAP_ENTRY
, Link
, EFI_GCD_MAP_SIGNATURE
);
1977 BuildIoDescriptor (Descriptor
, Entry
);
1979 Link
= Link
->ForwardLink
;
1981 Status
= EFI_SUCCESS
;
1984 CoreReleaseGcdIoLock ();
1990 Converts a Resource Descriptor HOB attributes mask to an EFI Memory Descriptor
1993 @param GcdMemoryType Type of resource in the GCD memory map.
1994 @param Attributes The attribute mask in the Resource Descriptor
1997 @return The capabilities mask for an EFI Memory Descriptor.
2001 CoreConvertResourceDescriptorHobAttributesToCapabilities (
2002 EFI_GCD_MEMORY_TYPE GcdMemoryType
,
2006 UINT64 Capabilities
;
2007 GCD_ATTRIBUTE_CONVERSION_ENTRY
*Conversion
;
2010 // Convert the Resource HOB Attributes to an EFI Memory Capabilities mask
2012 for (Capabilities
= 0, Conversion
= mAttributeConversionTable
; Conversion
->Attribute
!= 0; Conversion
++) {
2013 if (Conversion
->Memory
|| ((GcdMemoryType
!= EfiGcdMemoryTypeSystemMemory
) && (GcdMemoryType
!= EfiGcdMemoryTypeMoreReliable
))) {
2014 if (Attributes
& Conversion
->Attribute
) {
2015 Capabilities
|= Conversion
->Capability
;
2020 return Capabilities
;
2024 Calculate total memory bin size neeeded.
2026 @return The total memory bin size neeeded.
2030 CalculateTotalMemoryBinSizeNeeded (
2038 // Loop through each memory type in the order specified by the gMemoryTypeInformation[] array
2041 for (Index
= 0; gMemoryTypeInformation
[Index
].Type
!= EfiMaxMemoryType
; Index
++) {
2042 TotalSize
+= LShiftU64 (gMemoryTypeInformation
[Index
].NumberOfPages
, EFI_PAGE_SHIFT
);
2049 External function. Initializes memory services based on the memory
2050 descriptor HOBs. This function is responsible for priming the memory
2051 map, so memory allocations and resource allocations can be made.
2052 The first part of this function can not depend on any memory services
2053 until at least one memory descriptor is provided to the memory services.
2055 @param HobStart The start address of the HOB.
2056 @param MemoryBaseAddress Start address of memory region found to init DXE
2058 @param MemoryLength Length of memory region found to init DXE core.
2060 @retval EFI_SUCCESS Memory services successfully initialized.
2064 CoreInitializeMemoryServices (
2066 OUT EFI_PHYSICAL_ADDRESS
*MemoryBaseAddress
,
2067 OUT UINT64
*MemoryLength
2070 EFI_PEI_HOB_POINTERS Hob
;
2071 EFI_MEMORY_TYPE_INFORMATION
*EfiMemoryTypeInformation
;
2074 EFI_HOB_HANDOFF_INFO_TABLE
*PhitHob
;
2075 EFI_HOB_RESOURCE_DESCRIPTOR
*ResourceHob
;
2076 EFI_HOB_RESOURCE_DESCRIPTOR
*PhitResourceHob
;
2077 EFI_PHYSICAL_ADDRESS BaseAddress
;
2080 UINT64 Capabilities
;
2081 EFI_PHYSICAL_ADDRESS TestedMemoryBaseAddress
;
2082 UINT64 TestedMemoryLength
;
2083 EFI_PHYSICAL_ADDRESS HighAddress
;
2084 EFI_HOB_GUID_TYPE
*GuidHob
;
2085 UINT32 ReservedCodePageNumber
;
2086 UINT64 MinimalMemorySizeNeeded
;
2089 // Point at the first HOB. This must be the PHIT HOB.
2091 Hob
.Raw
= *HobStart
;
2092 ASSERT (GET_HOB_TYPE (Hob
) == EFI_HOB_TYPE_HANDOFF
);
2095 // Initialize the spin locks and maps in the memory services.
2096 // Also fill in the memory services into the EFI Boot Services Table
2098 CoreInitializePool ();
2101 // Initialize Local Variables
2103 PhitResourceHob
= NULL
;
2110 // Cache the PHIT HOB for later use
2112 PhitHob
= Hob
.HandoffInformationTable
;
2114 if (PcdGet64(PcdLoadModuleAtFixAddressEnable
) != 0) {
2115 ReservedCodePageNumber
= PcdGet32(PcdLoadFixAddressRuntimeCodePageNumber
);
2116 ReservedCodePageNumber
+= PcdGet32(PcdLoadFixAddressBootTimeCodePageNumber
);
2119 // cache the Top address for loading modules at Fixed Address
2121 gLoadModuleAtFixAddressConfigurationTable
.DxeCodeTopAddress
= PhitHob
->EfiMemoryTop
2122 + EFI_PAGES_TO_SIZE(ReservedCodePageNumber
);
2125 // See if a Memory Type Information HOB is available
2127 GuidHob
= GetFirstGuidHob (&gEfiMemoryTypeInformationGuid
);
2128 if (GuidHob
!= NULL
) {
2129 EfiMemoryTypeInformation
= GET_GUID_HOB_DATA (GuidHob
);
2130 DataSize
= GET_GUID_HOB_DATA_SIZE (GuidHob
);
2131 if (EfiMemoryTypeInformation
!= NULL
&& DataSize
> 0 && DataSize
<= (EfiMaxMemoryType
+ 1) * sizeof (EFI_MEMORY_TYPE_INFORMATION
)) {
2132 CopyMem (&gMemoryTypeInformation
, EfiMemoryTypeInformation
, DataSize
);
2137 // Include the total memory bin size needed to make sure memory bin could be allocated successfully.
2139 MinimalMemorySizeNeeded
= MINIMUM_INITIAL_MEMORY_SIZE
+ CalculateTotalMemoryBinSizeNeeded ();
2142 // Find the Resource Descriptor HOB that contains PHIT range EfiFreeMemoryBottom..EfiFreeMemoryTop
2145 for (Hob
.Raw
= *HobStart
; !END_OF_HOB_LIST(Hob
); Hob
.Raw
= GET_NEXT_HOB(Hob
)) {
2147 // Skip all HOBs except Resource Descriptor HOBs
2149 if (GET_HOB_TYPE (Hob
) != EFI_HOB_TYPE_RESOURCE_DESCRIPTOR
) {
2154 // Skip Resource Descriptor HOBs that do not describe tested system memory
2156 ResourceHob
= Hob
.ResourceDescriptor
;
2157 if (ResourceHob
->ResourceType
!= EFI_RESOURCE_SYSTEM_MEMORY
) {
2160 if ((ResourceHob
->ResourceAttribute
& MEMORY_ATTRIBUTE_MASK
) != TESTED_MEMORY_ATTRIBUTES
) {
2165 // Skip Resource Descriptor HOBs that do not contain the PHIT range EfiFreeMemoryBottom..EfiFreeMemoryTop
2167 if (PhitHob
->EfiFreeMemoryBottom
< ResourceHob
->PhysicalStart
) {
2170 if (PhitHob
->EfiFreeMemoryTop
> (ResourceHob
->PhysicalStart
+ ResourceHob
->ResourceLength
)) {
2175 // Cache the resource descriptor HOB for the memory region described by the PHIT HOB
2177 PhitResourceHob
= ResourceHob
;
2181 // Compute range between PHIT EfiMemoryTop and the end of the Resource Descriptor HOB
2183 Attributes
= PhitResourceHob
->ResourceAttribute
;
2184 BaseAddress
= PageAlignAddress (PhitHob
->EfiMemoryTop
);
2185 Length
= PageAlignLength (ResourceHob
->PhysicalStart
+ ResourceHob
->ResourceLength
- BaseAddress
);
2186 if (Length
< MinimalMemorySizeNeeded
) {
2188 // If that range is not large enough to intialize the DXE Core, then
2189 // Compute range between PHIT EfiFreeMemoryBottom and PHIT EfiFreeMemoryTop
2191 BaseAddress
= PageAlignAddress (PhitHob
->EfiFreeMemoryBottom
);
2192 Length
= PageAlignLength (PhitHob
->EfiFreeMemoryTop
- BaseAddress
);
2193 if (Length
< MinimalMemorySizeNeeded
) {
2195 // If that range is not large enough to intialize the DXE Core, then
2196 // Compute range between the start of the Resource Descriptor HOB and the start of the HOB List
2198 BaseAddress
= PageAlignAddress (ResourceHob
->PhysicalStart
);
2199 Length
= PageAlignLength ((UINT64
)((UINTN
)*HobStart
- BaseAddress
));
2206 // Assert if a resource descriptor HOB for the memory region described by the PHIT was not found
2211 // Take the range in the resource descriptor HOB for the memory region described
2212 // by the PHIT as higher priority if it is big enough. It can make the memory bin
2213 // allocated to be at the same memory region with PHIT that has more better compatibility
2214 // to avoid memory fragmentation for some code practices assume and allocate <4G ACPI memory.
2216 if (Length
< MinimalMemorySizeNeeded
) {
2218 // Search all the resource descriptor HOBs from the highest possible addresses down for a memory
2219 // region that is big enough to initialize the DXE core. Always skip the PHIT Resource HOB.
2220 // The max address must be within the physically addressible range for the processor.
2222 HighAddress
= MAX_ADDRESS
;
2223 for (Hob
.Raw
= *HobStart
; !END_OF_HOB_LIST(Hob
); Hob
.Raw
= GET_NEXT_HOB(Hob
)) {
2225 // Skip the Resource Descriptor HOB that contains the PHIT
2227 if (Hob
.ResourceDescriptor
== PhitResourceHob
) {
2231 // Skip all HOBs except Resource Descriptor HOBs
2233 if (GET_HOB_TYPE (Hob
) != EFI_HOB_TYPE_RESOURCE_DESCRIPTOR
) {
2238 // Skip Resource Descriptor HOBs that do not describe tested system memory below MAX_ADDRESS
2240 ResourceHob
= Hob
.ResourceDescriptor
;
2241 if (ResourceHob
->ResourceType
!= EFI_RESOURCE_SYSTEM_MEMORY
) {
2244 if ((ResourceHob
->ResourceAttribute
& MEMORY_ATTRIBUTE_MASK
) != TESTED_MEMORY_ATTRIBUTES
) {
2247 if ((ResourceHob
->PhysicalStart
+ ResourceHob
->ResourceLength
) > (EFI_PHYSICAL_ADDRESS
)MAX_ADDRESS
) {
2252 // Skip Resource Descriptor HOBs that are below a previously found Resource Descriptor HOB
2254 if (HighAddress
!= (EFI_PHYSICAL_ADDRESS
)MAX_ADDRESS
&& ResourceHob
->PhysicalStart
<= HighAddress
) {
2259 // Skip Resource Descriptor HOBs that are not large enough to initilize the DXE Core
2261 TestedMemoryBaseAddress
= PageAlignAddress (ResourceHob
->PhysicalStart
);
2262 TestedMemoryLength
= PageAlignLength (ResourceHob
->PhysicalStart
+ ResourceHob
->ResourceLength
- TestedMemoryBaseAddress
);
2263 if (TestedMemoryLength
< MinimalMemorySizeNeeded
) {
2268 // Save the range described by the Resource Descriptor that is large enough to initilize the DXE Core
2270 BaseAddress
= TestedMemoryBaseAddress
;
2271 Length
= TestedMemoryLength
;
2272 Attributes
= ResourceHob
->ResourceAttribute
;
2273 HighAddress
= ResourceHob
->PhysicalStart
;
2277 DEBUG ((EFI_D_INFO
, "CoreInitializeMemoryServices:\n"));
2278 DEBUG ((EFI_D_INFO
, " BaseAddress - 0x%lx Length - 0x%lx MinimalMemorySizeNeeded - 0x%lx\n", BaseAddress
, Length
, MinimalMemorySizeNeeded
));
2281 // If no memory regions are found that are big enough to initialize the DXE core, then ASSERT().
2283 ASSERT (Length
>= MinimalMemorySizeNeeded
);
2286 // Convert the Resource HOB Attributes to an EFI Memory Capabilities mask
2288 if ((Attributes
& EFI_RESOURCE_ATTRIBUTE_MORE_RELIABLE
) == EFI_RESOURCE_ATTRIBUTE_MORE_RELIABLE
) {
2289 Capabilities
= CoreConvertResourceDescriptorHobAttributesToCapabilities (EfiGcdMemoryTypeMoreReliable
, Attributes
);
2291 Capabilities
= CoreConvertResourceDescriptorHobAttributesToCapabilities (EfiGcdMemoryTypeSystemMemory
, Attributes
);
2295 // Declare the very first memory region, so the EFI Memory Services are available.
2297 CoreAddMemoryDescriptor (
2298 EfiConventionalMemory
,
2300 RShiftU64 (Length
, EFI_PAGE_SHIFT
),
2304 *MemoryBaseAddress
= BaseAddress
;
2305 *MemoryLength
= Length
;
2312 External function. Initializes the GCD and memory services based on the memory
2313 descriptor HOBs. This function is responsible for priming the GCD map and the
2314 memory map, so memory allocations and resource allocations can be made. The
2315 HobStart will be relocated to a pool buffer.
2317 @param HobStart The start address of the HOB
2318 @param MemoryBaseAddress Start address of memory region found to init DXE
2320 @param MemoryLength Length of memory region found to init DXE core.
2322 @retval EFI_SUCCESS GCD services successfully initialized.
2326 CoreInitializeGcdServices (
2327 IN OUT VOID
**HobStart
,
2328 IN EFI_PHYSICAL_ADDRESS MemoryBaseAddress
,
2329 IN UINT64 MemoryLength
2332 EFI_PEI_HOB_POINTERS Hob
;
2334 EFI_HOB_HANDOFF_INFO_TABLE
*PhitHob
;
2335 UINT8 SizeOfMemorySpace
;
2336 UINT8 SizeOfIoSpace
;
2337 EFI_HOB_RESOURCE_DESCRIPTOR
*ResourceHob
;
2338 EFI_PHYSICAL_ADDRESS BaseAddress
;
2341 EFI_GCD_MAP_ENTRY
*Entry
;
2342 EFI_GCD_MEMORY_TYPE GcdMemoryType
;
2343 EFI_GCD_IO_TYPE GcdIoType
;
2344 EFI_GCD_MEMORY_SPACE_DESCRIPTOR Descriptor
;
2345 EFI_HOB_MEMORY_ALLOCATION
*MemoryHob
;
2346 EFI_HOB_FIRMWARE_VOLUME
*FirmwareVolumeHob
;
2347 UINTN NumberOfDescriptors
;
2348 EFI_GCD_MEMORY_SPACE_DESCRIPTOR
*MemorySpaceMap
;
2350 UINT64 Capabilities
;
2351 EFI_HOB_CPU
* CpuHob
;
2352 EFI_GCD_MEMORY_SPACE_DESCRIPTOR
*MemorySpaceMapHobList
;
2355 // Cache the PHIT HOB for later use
2357 PhitHob
= (EFI_HOB_HANDOFF_INFO_TABLE
*)(*HobStart
);
2360 // Get the number of address lines in the I/O and Memory space for the CPU
2362 CpuHob
= GetFirstHob (EFI_HOB_TYPE_CPU
);
2363 ASSERT (CpuHob
!= NULL
);
2364 SizeOfMemorySpace
= CpuHob
->SizeOfMemorySpace
;
2365 SizeOfIoSpace
= CpuHob
->SizeOfIoSpace
;
2368 // Initialize the GCD Memory Space Map
2370 Entry
= AllocateCopyPool (sizeof (EFI_GCD_MAP_ENTRY
), &mGcdMemorySpaceMapEntryTemplate
);
2371 ASSERT (Entry
!= NULL
);
2373 Entry
->EndAddress
= LShiftU64 (1, SizeOfMemorySpace
) - 1;
2375 InsertHeadList (&mGcdMemorySpaceMap
, &Entry
->Link
);
2377 CoreDumpGcdMemorySpaceMap (TRUE
);
2380 // Initialize the GCD I/O Space Map
2382 Entry
= AllocateCopyPool (sizeof (EFI_GCD_MAP_ENTRY
), &mGcdIoSpaceMapEntryTemplate
);
2383 ASSERT (Entry
!= NULL
);
2385 Entry
->EndAddress
= LShiftU64 (1, SizeOfIoSpace
) - 1;
2387 InsertHeadList (&mGcdIoSpaceMap
, &Entry
->Link
);
2389 CoreDumpGcdIoSpaceMap (TRUE
);
2392 // Walk the HOB list and add all resource descriptors to the GCD
2394 for (Hob
.Raw
= *HobStart
; !END_OF_HOB_LIST(Hob
); Hob
.Raw
= GET_NEXT_HOB(Hob
)) {
2396 GcdMemoryType
= EfiGcdMemoryTypeNonExistent
;
2397 GcdIoType
= EfiGcdIoTypeNonExistent
;
2399 if (GET_HOB_TYPE (Hob
) == EFI_HOB_TYPE_RESOURCE_DESCRIPTOR
) {
2401 ResourceHob
= Hob
.ResourceDescriptor
;
2403 switch (ResourceHob
->ResourceType
) {
2404 case EFI_RESOURCE_SYSTEM_MEMORY
:
2405 if ((ResourceHob
->ResourceAttribute
& MEMORY_ATTRIBUTE_MASK
) == TESTED_MEMORY_ATTRIBUTES
) {
2406 if ((ResourceHob
->ResourceAttribute
& EFI_RESOURCE_ATTRIBUTE_MORE_RELIABLE
) == EFI_RESOURCE_ATTRIBUTE_MORE_RELIABLE
) {
2407 GcdMemoryType
= EfiGcdMemoryTypeMoreReliable
;
2409 GcdMemoryType
= EfiGcdMemoryTypeSystemMemory
;
2412 if ((ResourceHob
->ResourceAttribute
& MEMORY_ATTRIBUTE_MASK
) == INITIALIZED_MEMORY_ATTRIBUTES
) {
2413 GcdMemoryType
= EfiGcdMemoryTypeReserved
;
2415 if ((ResourceHob
->ResourceAttribute
& MEMORY_ATTRIBUTE_MASK
) == PRESENT_MEMORY_ATTRIBUTES
) {
2416 GcdMemoryType
= EfiGcdMemoryTypeReserved
;
2418 if ((ResourceHob
->ResourceAttribute
& EFI_RESOURCE_ATTRIBUTE_PERSISTENT
) == EFI_RESOURCE_ATTRIBUTE_PERSISTENT
) {
2419 GcdMemoryType
= EfiGcdMemoryTypePersistent
;
2422 case EFI_RESOURCE_MEMORY_MAPPED_IO
:
2423 case EFI_RESOURCE_FIRMWARE_DEVICE
:
2424 GcdMemoryType
= EfiGcdMemoryTypeMemoryMappedIo
;
2426 case EFI_RESOURCE_MEMORY_MAPPED_IO_PORT
:
2427 case EFI_RESOURCE_MEMORY_RESERVED
:
2428 GcdMemoryType
= EfiGcdMemoryTypeReserved
;
2430 case EFI_RESOURCE_IO
:
2431 GcdIoType
= EfiGcdIoTypeIo
;
2433 case EFI_RESOURCE_IO_RESERVED
:
2434 GcdIoType
= EfiGcdIoTypeReserved
;
2438 if (GcdMemoryType
!= EfiGcdMemoryTypeNonExistent
) {
2440 // Validate the Resource HOB Attributes
2442 CoreValidateResourceDescriptorHobAttributes (ResourceHob
->ResourceAttribute
);
2445 // Convert the Resource HOB Attributes to an EFI Memory Capabilities mask
2447 Capabilities
= CoreConvertResourceDescriptorHobAttributesToCapabilities (
2449 ResourceHob
->ResourceAttribute
2452 Status
= CoreInternalAddMemorySpace (
2454 ResourceHob
->PhysicalStart
,
2455 ResourceHob
->ResourceLength
,
2460 if (GcdIoType
!= EfiGcdIoTypeNonExistent
) {
2461 Status
= CoreAddIoSpace (
2463 ResourceHob
->PhysicalStart
,
2464 ResourceHob
->ResourceLength
2471 // Allocate first memory region from the GCD by the DXE core
2473 Status
= CoreGetMemorySpaceDescriptor (MemoryBaseAddress
, &Descriptor
);
2474 if (!EFI_ERROR (Status
)) {
2475 ASSERT ((Descriptor
.GcdMemoryType
== EfiGcdMemoryTypeSystemMemory
) ||
2476 (Descriptor
.GcdMemoryType
== EfiGcdMemoryTypeMoreReliable
));
2477 Status
= CoreAllocateMemorySpace (
2478 EfiGcdAllocateAddress
,
2479 Descriptor
.GcdMemoryType
,
2483 gDxeCoreImageHandle
,
2489 // Walk the HOB list and allocate all memory space that is consumed by memory allocation HOBs,
2490 // and Firmware Volume HOBs. Also update the EFI Memory Map with the memory allocation HOBs.
2492 for (Hob
.Raw
= *HobStart
; !END_OF_HOB_LIST(Hob
); Hob
.Raw
= GET_NEXT_HOB(Hob
)) {
2493 if (GET_HOB_TYPE (Hob
) == EFI_HOB_TYPE_MEMORY_ALLOCATION
) {
2494 MemoryHob
= Hob
.MemoryAllocation
;
2495 BaseAddress
= MemoryHob
->AllocDescriptor
.MemoryBaseAddress
;
2496 Status
= CoreGetMemorySpaceDescriptor (BaseAddress
, &Descriptor
);
2497 if (!EFI_ERROR (Status
)) {
2498 Status
= CoreAllocateMemorySpace (
2499 EfiGcdAllocateAddress
,
2500 Descriptor
.GcdMemoryType
,
2502 MemoryHob
->AllocDescriptor
.MemoryLength
,
2504 gDxeCoreImageHandle
,
2507 if (!EFI_ERROR (Status
) &&
2508 ((Descriptor
.GcdMemoryType
== EfiGcdMemoryTypeSystemMemory
) ||
2509 (Descriptor
.GcdMemoryType
== EfiGcdMemoryTypeMoreReliable
))) {
2510 CoreAddMemoryDescriptor (
2511 MemoryHob
->AllocDescriptor
.MemoryType
,
2512 MemoryHob
->AllocDescriptor
.MemoryBaseAddress
,
2513 RShiftU64 (MemoryHob
->AllocDescriptor
.MemoryLength
, EFI_PAGE_SHIFT
),
2514 Descriptor
.Capabilities
& (~EFI_MEMORY_RUNTIME
)
2520 if (GET_HOB_TYPE (Hob
) == EFI_HOB_TYPE_FV
) {
2521 FirmwareVolumeHob
= Hob
.FirmwareVolume
;
2522 BaseAddress
= FirmwareVolumeHob
->BaseAddress
;
2523 Status
= CoreAllocateMemorySpace (
2524 EfiGcdAllocateAddress
,
2525 EfiGcdMemoryTypeMemoryMappedIo
,
2527 FirmwareVolumeHob
->Length
,
2529 gDxeCoreImageHandle
,
2536 // Add and allocate the remaining unallocated system memory to the memory services.
2538 Status
= CoreGetMemorySpaceMap (&NumberOfDescriptors
, &MemorySpaceMap
);
2539 ASSERT (Status
== EFI_SUCCESS
);
2541 MemorySpaceMapHobList
= NULL
;
2542 for (Index
= 0; Index
< NumberOfDescriptors
; Index
++) {
2543 if ((MemorySpaceMap
[Index
].GcdMemoryType
== EfiGcdMemoryTypeSystemMemory
) ||
2544 (MemorySpaceMap
[Index
].GcdMemoryType
== EfiGcdMemoryTypeMoreReliable
)) {
2545 if (MemorySpaceMap
[Index
].ImageHandle
== NULL
) {
2546 BaseAddress
= PageAlignAddress (MemorySpaceMap
[Index
].BaseAddress
);
2547 Length
= PageAlignLength (MemorySpaceMap
[Index
].BaseAddress
+ MemorySpaceMap
[Index
].Length
- BaseAddress
);
2548 if (Length
== 0 || MemorySpaceMap
[Index
].BaseAddress
+ MemorySpaceMap
[Index
].Length
< BaseAddress
) {
2551 if (((UINTN
) MemorySpaceMap
[Index
].BaseAddress
<= (UINTN
) (*HobStart
)) &&
2552 ((UINTN
) (MemorySpaceMap
[Index
].BaseAddress
+ MemorySpaceMap
[Index
].Length
) >= (UINTN
) PhitHob
->EfiFreeMemoryBottom
)) {
2554 // Skip the memory space that covers HOB List, it should be processed
2555 // after HOB List relocation to avoid the resources allocated by others
2556 // to corrupt HOB List before its relocation.
2558 MemorySpaceMapHobList
= &MemorySpaceMap
[Index
];
2561 CoreAddMemoryDescriptor (
2562 EfiConventionalMemory
,
2564 RShiftU64 (Length
, EFI_PAGE_SHIFT
),
2565 MemorySpaceMap
[Index
].Capabilities
& (~EFI_MEMORY_RUNTIME
)
2567 Status
= CoreAllocateMemorySpace (
2568 EfiGcdAllocateAddress
,
2569 MemorySpaceMap
[Index
].GcdMemoryType
,
2573 gDxeCoreImageHandle
,
2581 // Relocate HOB List to an allocated pool buffer.
2582 // The relocation should be at after all the tested memory resources added
2583 // (except the memory space that covers HOB List) to the memory services,
2584 // because the memory resource found in CoreInitializeMemoryServices()
2585 // may have not enough remaining resource for HOB List.
2587 NewHobList
= AllocateCopyPool (
2588 (UINTN
) PhitHob
->EfiFreeMemoryBottom
- (UINTN
) (*HobStart
),
2591 ASSERT (NewHobList
!= NULL
);
2593 *HobStart
= NewHobList
;
2594 gHobList
= NewHobList
;
2596 if (MemorySpaceMapHobList
!= NULL
) {
2598 // Add and allocate the memory space that covers HOB List to the memory services
2599 // after HOB List relocation.
2601 BaseAddress
= PageAlignAddress (MemorySpaceMapHobList
->BaseAddress
);
2602 Length
= PageAlignLength (MemorySpaceMapHobList
->BaseAddress
+ MemorySpaceMapHobList
->Length
- BaseAddress
);
2603 CoreAddMemoryDescriptor (
2604 EfiConventionalMemory
,
2606 RShiftU64 (Length
, EFI_PAGE_SHIFT
),
2607 MemorySpaceMapHobList
->Capabilities
& (~EFI_MEMORY_RUNTIME
)
2609 Status
= CoreAllocateMemorySpace (
2610 EfiGcdAllocateAddress
,
2611 MemorySpaceMapHobList
->GcdMemoryType
,
2615 gDxeCoreImageHandle
,
2620 CoreFreePool (MemorySpaceMap
);