2 The file contains the GCD related services in the EFI Boot Services Table.
3 The GCD services are used to manage the memory and I/O regions that
4 are accessible to the CPU that is executing the DXE core.
6 Copyright (c) 2006 - 2015, Intel Corporation. All rights reserved.<BR>
7 This program and the accompanying materials
8 are licensed and made available under the terms and conditions of the BSD License
9 which accompanies this distribution. The full text of the license may be found at
10 http://opensource.org/licenses/bsd-license.php
12 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
13 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
20 #define MINIMUM_INITIAL_MEMORY_SIZE 0x10000
22 #define MEMORY_ATTRIBUTE_MASK (EFI_RESOURCE_ATTRIBUTE_PRESENT | \
23 EFI_RESOURCE_ATTRIBUTE_INITIALIZED | \
24 EFI_RESOURCE_ATTRIBUTE_TESTED | \
25 EFI_RESOURCE_ATTRIBUTE_READ_PROTECTED | \
26 EFI_RESOURCE_ATTRIBUTE_WRITE_PROTECTED | \
27 EFI_RESOURCE_ATTRIBUTE_EXECUTION_PROTECTED | \
28 EFI_RESOURCE_ATTRIBUTE_READ_ONLY_PROTECTED | \
29 EFI_RESOURCE_ATTRIBUTE_16_BIT_IO | \
30 EFI_RESOURCE_ATTRIBUTE_32_BIT_IO | \
31 EFI_RESOURCE_ATTRIBUTE_64_BIT_IO | \
32 EFI_RESOURCE_ATTRIBUTE_PERSISTENT )
34 #define TESTED_MEMORY_ATTRIBUTES (EFI_RESOURCE_ATTRIBUTE_PRESENT | \
35 EFI_RESOURCE_ATTRIBUTE_INITIALIZED | \
36 EFI_RESOURCE_ATTRIBUTE_TESTED )
38 #define INITIALIZED_MEMORY_ATTRIBUTES (EFI_RESOURCE_ATTRIBUTE_PRESENT | \
39 EFI_RESOURCE_ATTRIBUTE_INITIALIZED )
41 #define PRESENT_MEMORY_ATTRIBUTES (EFI_RESOURCE_ATTRIBUTE_PRESENT)
43 #define INVALID_CPU_ARCH_ATTRIBUTES 0xffffffff
48 EFI_LOCK mGcdMemorySpaceLock
= EFI_INITIALIZE_LOCK_VARIABLE (TPL_NOTIFY
);
49 EFI_LOCK mGcdIoSpaceLock
= EFI_INITIALIZE_LOCK_VARIABLE (TPL_NOTIFY
);
50 LIST_ENTRY mGcdMemorySpaceMap
= INITIALIZE_LIST_HEAD_VARIABLE (mGcdMemorySpaceMap
);
51 LIST_ENTRY mGcdIoSpaceMap
= INITIALIZE_LIST_HEAD_VARIABLE (mGcdIoSpaceMap
);
53 EFI_GCD_MAP_ENTRY mGcdMemorySpaceMapEntryTemplate
= {
54 EFI_GCD_MAP_SIGNATURE
,
63 EfiGcdMemoryTypeNonExistent
,
69 EFI_GCD_MAP_ENTRY mGcdIoSpaceMapEntryTemplate
= {
70 EFI_GCD_MAP_SIGNATURE
,
79 (EFI_GCD_MEMORY_TYPE
) 0,
80 EfiGcdIoTypeNonExistent
,
85 GCD_ATTRIBUTE_CONVERSION_ENTRY mAttributeConversionTable
[] = {
86 { EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE
, EFI_MEMORY_UC
, TRUE
},
87 { EFI_RESOURCE_ATTRIBUTE_UNCACHED_EXPORTED
, EFI_MEMORY_UCE
, TRUE
},
88 { EFI_RESOURCE_ATTRIBUTE_WRITE_COMBINEABLE
, EFI_MEMORY_WC
, TRUE
},
89 { EFI_RESOURCE_ATTRIBUTE_WRITE_THROUGH_CACHEABLE
, EFI_MEMORY_WT
, TRUE
},
90 { EFI_RESOURCE_ATTRIBUTE_WRITE_BACK_CACHEABLE
, EFI_MEMORY_WB
, TRUE
},
91 { EFI_RESOURCE_ATTRIBUTE_READ_PROTECTABLE
, EFI_MEMORY_RP
, TRUE
},
92 { EFI_RESOURCE_ATTRIBUTE_WRITE_PROTECTABLE
, EFI_MEMORY_WP
, TRUE
},
93 { EFI_RESOURCE_ATTRIBUTE_EXECUTION_PROTECTABLE
, EFI_MEMORY_XP
, TRUE
},
94 { EFI_RESOURCE_ATTRIBUTE_READ_ONLY_PROTECTABLE
, EFI_MEMORY_RO
, TRUE
},
95 { EFI_RESOURCE_ATTRIBUTE_PRESENT
, EFI_MEMORY_PRESENT
, FALSE
},
96 { EFI_RESOURCE_ATTRIBUTE_INITIALIZED
, EFI_MEMORY_INITIALIZED
, FALSE
},
97 { EFI_RESOURCE_ATTRIBUTE_TESTED
, EFI_MEMORY_TESTED
, FALSE
},
98 { EFI_RESOURCE_ATTRIBUTE_PERSISTABLE
, EFI_MEMORY_NV
, TRUE
},
103 /// Lookup table used to print GCD Memory Space Map
105 GLOBAL_REMOVE_IF_UNREFERENCED CONST CHAR8
*mGcdMemoryTypeNames
[] = {
106 "NonExist ", // EfiGcdMemoryTypeNonExistent
107 "Reserved ", // EfiGcdMemoryTypeReserved
108 "SystemMem", // EfiGcdMemoryTypeSystemMemory
109 "MMIO ", // EfiGcdMemoryTypeMemoryMappedIo
110 "PersistentMem",// EfiGcdMemoryTypePersistentMemory
111 "Unknown " // EfiGcdMemoryTypeMaximum
115 /// Lookup table used to print GCD I/O Space Map
117 GLOBAL_REMOVE_IF_UNREFERENCED CONST CHAR8
*mGcdIoTypeNames
[] = {
118 "NonExist", // EfiGcdIoTypeNonExistent
119 "Reserved", // EfiGcdIoTypeReserved
120 "I/O ", // EfiGcdIoTypeIo
121 "Unknown " // EfiGcdIoTypeMaximum
125 /// Lookup table used to print GCD Allocation Types
127 GLOBAL_REMOVE_IF_UNREFERENCED CONST CHAR8
*mGcdAllocationTypeNames
[] = {
128 "AnySearchBottomUp ", // EfiGcdAllocateAnySearchBottomUp
129 "MaxAddressSearchBottomUp ", // EfiGcdAllocateMaxAddressSearchBottomUp
130 "AtAddress ", // EfiGcdAllocateAddress
131 "AnySearchTopDown ", // EfiGcdAllocateAnySearchTopDown
132 "MaxAddressSearchTopDown ", // EfiGcdAllocateMaxAddressSearchTopDown
133 "Unknown " // EfiGcdMaxAllocateType
137 Dump the entire contents if the GCD Memory Space Map using DEBUG() macros when
138 PcdDebugPrintErrorLevel has the DEBUG_GCD bit set.
140 @param InitialMap TRUE if the initial GCD Memory Map is being dumped. Otherwise, FALSE.
145 CoreDumpGcdMemorySpaceMap (
151 UINTN NumberOfDescriptors
;
152 EFI_GCD_MEMORY_SPACE_DESCRIPTOR
*MemorySpaceMap
;
155 Status
= CoreGetMemorySpaceMap (&NumberOfDescriptors
, &MemorySpaceMap
);
156 ASSERT (Status
== EFI_SUCCESS
&& MemorySpaceMap
!= NULL
);
159 DEBUG ((DEBUG_GCD
, "GCD:Initial GCD Memory Space Map\n"));
161 DEBUG ((DEBUG_GCD
, "GCDMemType Range Capabilities Attributes \n"));
162 DEBUG ((DEBUG_GCD
, "========== ================================= ================ ================\n"));
163 for (Index
= 0; Index
< NumberOfDescriptors
; Index
++) {
164 DEBUG ((DEBUG_GCD
, "%a %016lx-%016lx %016lx %016lx%c\n",
165 mGcdMemoryTypeNames
[MIN (MemorySpaceMap
[Index
].GcdMemoryType
, EfiGcdMemoryTypeMaximum
)],
166 MemorySpaceMap
[Index
].BaseAddress
,
167 MemorySpaceMap
[Index
].BaseAddress
+ MemorySpaceMap
[Index
].Length
- 1,
168 MemorySpaceMap
[Index
].Capabilities
,
169 MemorySpaceMap
[Index
].Attributes
,
170 MemorySpaceMap
[Index
].ImageHandle
== NULL
? ' ' : '*'
173 DEBUG ((DEBUG_GCD
, "\n"));
174 FreePool (MemorySpaceMap
);
179 Dump the entire contents if the GCD I/O Space Map using DEBUG() macros when
180 PcdDebugPrintErrorLevel has the DEBUG_GCD bit set.
182 @param InitialMap TRUE if the initial GCD I/O Map is being dumped. Otherwise, FALSE.
187 CoreDumpGcdIoSpaceMap (
193 UINTN NumberOfDescriptors
;
194 EFI_GCD_IO_SPACE_DESCRIPTOR
*IoSpaceMap
;
197 Status
= CoreGetIoSpaceMap (&NumberOfDescriptors
, &IoSpaceMap
);
198 ASSERT (Status
== EFI_SUCCESS
&& IoSpaceMap
!= NULL
);
201 DEBUG ((DEBUG_GCD
, "GCD:Initial GCD I/O Space Map\n"));
204 DEBUG ((DEBUG_GCD
, "GCDIoType Range \n"));
205 DEBUG ((DEBUG_GCD
, "========== =================================\n"));
206 for (Index
= 0; Index
< NumberOfDescriptors
; Index
++) {
207 DEBUG ((DEBUG_GCD
, "%a %016lx-%016lx%c\n",
208 mGcdIoTypeNames
[MIN (IoSpaceMap
[Index
].GcdIoType
, EfiGcdIoTypeMaximum
)],
209 IoSpaceMap
[Index
].BaseAddress
,
210 IoSpaceMap
[Index
].BaseAddress
+ IoSpaceMap
[Index
].Length
- 1,
211 IoSpaceMap
[Index
].ImageHandle
== NULL
? ' ' : '*'
214 DEBUG ((DEBUG_GCD
, "\n"));
215 FreePool (IoSpaceMap
);
220 Validate resource descriptor HOB's attributes.
222 If Attributes includes some memory resource's settings, it should include
223 the corresponding capabilites also.
225 @param Attributes Resource descriptor HOB attributes.
229 CoreValidateResourceDescriptorHobAttributes (
233 ASSERT (((Attributes
& EFI_RESOURCE_ATTRIBUTE_READ_PROTECTED
) == 0) ||
234 ((Attributes
& EFI_RESOURCE_ATTRIBUTE_READ_PROTECTABLE
) != 0));
235 ASSERT (((Attributes
& EFI_RESOURCE_ATTRIBUTE_WRITE_PROTECTED
) == 0) ||
236 ((Attributes
& EFI_RESOURCE_ATTRIBUTE_WRITE_PROTECTABLE
) != 0));
237 ASSERT (((Attributes
& EFI_RESOURCE_ATTRIBUTE_EXECUTION_PROTECTED
) == 0) ||
238 ((Attributes
& EFI_RESOURCE_ATTRIBUTE_EXECUTION_PROTECTABLE
) != 0));
239 ASSERT (((Attributes
& EFI_RESOURCE_ATTRIBUTE_READ_ONLY_PROTECTED
) == 0) ||
240 ((Attributes
& EFI_RESOURCE_ATTRIBUTE_READ_ONLY_PROTECTABLE
) != 0));
241 ASSERT (((Attributes
& EFI_RESOURCE_ATTRIBUTE_PERSISTENT
) == 0) ||
242 ((Attributes
& EFI_RESOURCE_ATTRIBUTE_PERSISTABLE
) != 0));
246 Acquire memory lock on mGcdMemorySpaceLock.
250 CoreAcquireGcdMemoryLock (
254 CoreAcquireLock (&mGcdMemorySpaceLock
);
260 Release memory lock on mGcdMemorySpaceLock.
264 CoreReleaseGcdMemoryLock (
268 CoreReleaseLock (&mGcdMemorySpaceLock
);
274 Acquire memory lock on mGcdIoSpaceLock.
278 CoreAcquireGcdIoLock (
282 CoreAcquireLock (&mGcdIoSpaceLock
);
287 Release memory lock on mGcdIoSpaceLock.
291 CoreReleaseGcdIoLock (
295 CoreReleaseLock (&mGcdIoSpaceLock
);
301 // GCD Initialization Worker Functions
304 Aligns a value to the specified boundary.
306 @param Value 64 bit value to align
307 @param Alignment Log base 2 of the boundary to align Value to
308 @param RoundUp TRUE if Value is to be rounded up to the nearest
309 aligned boundary. FALSE is Value is to be
310 rounded down to the nearest aligned boundary.
312 @return A 64 bit value is the aligned to the value nearest Value with an alignment by Alignment.
322 UINT64 AlignmentMask
;
324 AlignmentMask
= LShiftU64 (1, Alignment
) - 1;
326 Value
+= AlignmentMask
;
328 return Value
& (~AlignmentMask
);
333 Aligns address to the page boundary.
335 @param Value 64 bit address to align
337 @return A 64 bit value is the aligned to the value nearest Value with an alignment by Alignment.
345 return AlignValue (Value
, EFI_PAGE_SHIFT
, TRUE
);
350 Aligns length to the page boundary.
352 @param Value 64 bit length to align
354 @return A 64 bit value is the aligned to the value nearest Value with an alignment by Alignment.
362 return AlignValue (Value
, EFI_PAGE_SHIFT
, FALSE
);
366 // GCD Memory Space Worker Functions
370 Allocate pool for two entries.
372 @param TopEntry An entry of GCD map
373 @param BottomEntry An entry of GCD map
375 @retval EFI_OUT_OF_RESOURCES No enough buffer to be allocated.
376 @retval EFI_SUCCESS Both entries successfully allocated.
380 CoreAllocateGcdMapEntry (
381 IN OUT EFI_GCD_MAP_ENTRY
**TopEntry
,
382 IN OUT EFI_GCD_MAP_ENTRY
**BottomEntry
385 *TopEntry
= AllocateZeroPool (sizeof (EFI_GCD_MAP_ENTRY
));
386 if (*TopEntry
== NULL
) {
387 return EFI_OUT_OF_RESOURCES
;
390 *BottomEntry
= AllocateZeroPool (sizeof (EFI_GCD_MAP_ENTRY
));
391 if (*BottomEntry
== NULL
) {
392 CoreFreePool (*TopEntry
);
393 return EFI_OUT_OF_RESOURCES
;
401 Internal function. Inserts a new descriptor into a sorted list
403 @param Link The linked list to insert the range BaseAddress
405 @param Entry A pointer to the entry that is inserted
406 @param BaseAddress The base address of the new range
407 @param Length The length of the new range in bytes
408 @param TopEntry Top pad entry to insert if needed.
409 @param BottomEntry Bottom pad entry to insert if needed.
411 @retval EFI_SUCCESS The new range was inserted into the linked list
415 CoreInsertGcdMapEntry (
417 IN EFI_GCD_MAP_ENTRY
*Entry
,
418 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
420 IN EFI_GCD_MAP_ENTRY
*TopEntry
,
421 IN EFI_GCD_MAP_ENTRY
*BottomEntry
424 ASSERT (Length
!= 0);
426 if (BaseAddress
> Entry
->BaseAddress
) {
427 ASSERT (BottomEntry
->Signature
== 0);
429 CopyMem (BottomEntry
, Entry
, sizeof (EFI_GCD_MAP_ENTRY
));
430 Entry
->BaseAddress
= BaseAddress
;
431 BottomEntry
->EndAddress
= BaseAddress
- 1;
432 InsertTailList (Link
, &BottomEntry
->Link
);
435 if ((BaseAddress
+ Length
- 1) < Entry
->EndAddress
) {
436 ASSERT (TopEntry
->Signature
== 0);
438 CopyMem (TopEntry
, Entry
, sizeof (EFI_GCD_MAP_ENTRY
));
439 TopEntry
->BaseAddress
= BaseAddress
+ Length
;
440 Entry
->EndAddress
= BaseAddress
+ Length
- 1;
441 InsertHeadList (Link
, &TopEntry
->Link
);
449 Merge the Gcd region specified by Link and its adjacent entry.
451 @param Link Specify the entry to be merged (with its
453 @param Forward Direction (forward or backward).
456 @retval EFI_SUCCESS Successfully returned.
457 @retval EFI_UNSUPPORTED These adjacent regions could not merge.
461 CoreMergeGcdMapEntry (
467 LIST_ENTRY
*AdjacentLink
;
468 EFI_GCD_MAP_ENTRY
*Entry
;
469 EFI_GCD_MAP_ENTRY
*AdjacentEntry
;
472 // Get adjacent entry
475 AdjacentLink
= Link
->ForwardLink
;
477 AdjacentLink
= Link
->BackLink
;
481 // If AdjacentLink is the head of the list, then no merge can be performed
483 if (AdjacentLink
== Map
) {
487 Entry
= CR (Link
, EFI_GCD_MAP_ENTRY
, Link
, EFI_GCD_MAP_SIGNATURE
);
488 AdjacentEntry
= CR (AdjacentLink
, EFI_GCD_MAP_ENTRY
, Link
, EFI_GCD_MAP_SIGNATURE
);
490 if (Entry
->Capabilities
!= AdjacentEntry
->Capabilities
) {
491 return EFI_UNSUPPORTED
;
493 if (Entry
->Attributes
!= AdjacentEntry
->Attributes
) {
494 return EFI_UNSUPPORTED
;
496 if (Entry
->GcdMemoryType
!= AdjacentEntry
->GcdMemoryType
) {
497 return EFI_UNSUPPORTED
;
499 if (Entry
->GcdIoType
!= AdjacentEntry
->GcdIoType
) {
500 return EFI_UNSUPPORTED
;
502 if (Entry
->ImageHandle
!= AdjacentEntry
->ImageHandle
) {
503 return EFI_UNSUPPORTED
;
505 if (Entry
->DeviceHandle
!= AdjacentEntry
->DeviceHandle
) {
506 return EFI_UNSUPPORTED
;
510 Entry
->EndAddress
= AdjacentEntry
->EndAddress
;
512 Entry
->BaseAddress
= AdjacentEntry
->BaseAddress
;
514 RemoveEntryList (AdjacentLink
);
515 CoreFreePool (AdjacentEntry
);
522 Merge adjacent entries on total chain.
524 @param TopEntry Top entry of GCD map.
525 @param BottomEntry Bottom entry of GCD map.
526 @param StartLink Start link of the list for this loop.
527 @param EndLink End link of the list for this loop.
530 @retval EFI_SUCCESS GCD map successfully cleaned up.
534 CoreCleanupGcdMapEntry (
535 IN EFI_GCD_MAP_ENTRY
*TopEntry
,
536 IN EFI_GCD_MAP_ENTRY
*BottomEntry
,
537 IN LIST_ENTRY
*StartLink
,
538 IN LIST_ENTRY
*EndLink
,
544 if (TopEntry
->Signature
== 0) {
545 CoreFreePool (TopEntry
);
547 if (BottomEntry
->Signature
== 0) {
548 CoreFreePool (BottomEntry
);
552 while (Link
!= EndLink
->ForwardLink
) {
553 CoreMergeGcdMapEntry (Link
, FALSE
, Map
);
554 Link
= Link
->ForwardLink
;
556 CoreMergeGcdMapEntry (EndLink
, TRUE
, Map
);
563 Search a segment of memory space in GCD map. The result is a range of GCD entry list.
565 @param BaseAddress The start address of the segment.
566 @param Length The length of the segment.
567 @param StartLink The first GCD entry involves this segment of
569 @param EndLink The first GCD entry involves this segment of
571 @param Map Points to the start entry to search.
573 @retval EFI_SUCCESS Successfully found the entry.
574 @retval EFI_NOT_FOUND Not found.
578 CoreSearchGcdMapEntry (
579 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
581 OUT LIST_ENTRY
**StartLink
,
582 OUT LIST_ENTRY
**EndLink
,
587 EFI_GCD_MAP_ENTRY
*Entry
;
589 ASSERT (Length
!= 0);
594 Link
= Map
->ForwardLink
;
595 while (Link
!= Map
) {
596 Entry
= CR (Link
, EFI_GCD_MAP_ENTRY
, Link
, EFI_GCD_MAP_SIGNATURE
);
597 if (BaseAddress
>= Entry
->BaseAddress
&& BaseAddress
<= Entry
->EndAddress
) {
600 if (*StartLink
!= NULL
) {
601 if ((BaseAddress
+ Length
- 1) >= Entry
->BaseAddress
&&
602 (BaseAddress
+ Length
- 1) <= Entry
->EndAddress
) {
607 Link
= Link
->ForwardLink
;
610 return EFI_NOT_FOUND
;
615 Count the amount of GCD map entries.
617 @param Map Points to the start entry to do the count loop.
623 CoreCountGcdMapEntry (
631 Link
= Map
->ForwardLink
;
632 while (Link
!= Map
) {
634 Link
= Link
->ForwardLink
;
643 Return the memory attribute specified by Attributes
645 @param Attributes A num with some attribute bits on.
647 @return The enum value of memory attribute.
651 ConverToCpuArchAttributes (
655 if ( (Attributes
& EFI_MEMORY_UC
) == EFI_MEMORY_UC
) {
656 return EFI_MEMORY_UC
;
659 if ( (Attributes
& EFI_MEMORY_WC
) == EFI_MEMORY_WC
) {
660 return EFI_MEMORY_WC
;
663 if ( (Attributes
& EFI_MEMORY_WT
) == EFI_MEMORY_WT
) {
664 return EFI_MEMORY_WT
;
667 if ( (Attributes
& EFI_MEMORY_WB
) == EFI_MEMORY_WB
) {
668 return EFI_MEMORY_WB
;
671 if ( (Attributes
& EFI_MEMORY_WP
) == EFI_MEMORY_WP
) {
672 return EFI_MEMORY_WP
;
675 return INVALID_CPU_ARCH_ATTRIBUTES
;
681 Do operation on a segment of memory space specified (add, free, remove, change attribute ...).
683 @param Operation The type of the operation
684 @param GcdMemoryType Additional information for the operation
685 @param GcdIoType Additional information for the operation
686 @param BaseAddress Start address of the segment
687 @param Length length of the segment
688 @param Capabilities The alterable attributes of a newly added entry
689 @param Attributes The attributes needs to be set
691 @retval EFI_INVALID_PARAMETER Length is 0 or address (length) not aligned when
693 @retval EFI_SUCCESS Action successfully done.
694 @retval EFI_UNSUPPORTED Could not find the proper descriptor on this
695 segment or set an upsupported attribute.
696 @retval EFI_ACCESS_DENIED Operate on an space non-exist or is used for an
698 @retval EFI_NOT_FOUND Free a non-using space or remove a non-exist
700 @retval EFI_OUT_OF_RESOURCES No buffer could be allocated.
701 @retval EFI_NOT_AVAILABLE_YET The attributes cannot be set because CPU architectural protocol
702 is not available yet.
707 IN EFI_GCD_MEMORY_TYPE GcdMemoryType
,
708 IN EFI_GCD_IO_TYPE GcdIoType
,
709 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
711 IN UINT64 Capabilities
,
718 EFI_GCD_MAP_ENTRY
*Entry
;
719 EFI_GCD_MAP_ENTRY
*TopEntry
;
720 EFI_GCD_MAP_ENTRY
*BottomEntry
;
721 LIST_ENTRY
*StartLink
;
723 UINT64 CpuArchAttributes
;
726 DEBUG ((DEBUG_GCD
, " Status = %r\n", EFI_INVALID_PARAMETER
));
727 return EFI_INVALID_PARAMETER
;
731 if ((Operation
& GCD_MEMORY_SPACE_OPERATION
) != 0) {
732 CoreAcquireGcdMemoryLock ();
733 Map
= &mGcdMemorySpaceMap
;
734 } else if ((Operation
& GCD_IO_SPACE_OPERATION
) != 0) {
735 CoreAcquireGcdIoLock ();
736 Map
= &mGcdIoSpaceMap
;
742 // Search for the list of descriptors that cover the range BaseAddress to BaseAddress+Length
744 Status
= CoreSearchGcdMapEntry (BaseAddress
, Length
, &StartLink
, &EndLink
, Map
);
745 if (EFI_ERROR (Status
)) {
746 Status
= EFI_UNSUPPORTED
;
750 ASSERT (StartLink
!= NULL
&& EndLink
!= NULL
);
753 // Verify that the list of descriptors are unallocated non-existent memory.
756 while (Link
!= EndLink
->ForwardLink
) {
757 Entry
= CR (Link
, EFI_GCD_MAP_ENTRY
, Link
, EFI_GCD_MAP_SIGNATURE
);
762 case GCD_ADD_MEMORY_OPERATION
:
763 if (Entry
->GcdMemoryType
!= EfiGcdMemoryTypeNonExistent
||
764 Entry
->ImageHandle
!= NULL
) {
765 Status
= EFI_ACCESS_DENIED
;
769 case GCD_ADD_IO_OPERATION
:
770 if (Entry
->GcdIoType
!= EfiGcdIoTypeNonExistent
||
771 Entry
->ImageHandle
!= NULL
) {
772 Status
= EFI_ACCESS_DENIED
;
779 case GCD_FREE_MEMORY_OPERATION
:
780 case GCD_FREE_IO_OPERATION
:
781 if (Entry
->ImageHandle
== NULL
) {
782 Status
= EFI_NOT_FOUND
;
789 case GCD_REMOVE_MEMORY_OPERATION
:
790 if (Entry
->GcdMemoryType
== EfiGcdMemoryTypeNonExistent
) {
791 Status
= EFI_NOT_FOUND
;
794 if (Entry
->ImageHandle
!= NULL
) {
795 Status
= EFI_ACCESS_DENIED
;
799 case GCD_REMOVE_IO_OPERATION
:
800 if (Entry
->GcdIoType
== EfiGcdIoTypeNonExistent
) {
801 Status
= EFI_NOT_FOUND
;
804 if (Entry
->ImageHandle
!= NULL
) {
805 Status
= EFI_ACCESS_DENIED
;
810 // Set attributes operation
812 case GCD_SET_ATTRIBUTES_MEMORY_OPERATION
:
813 if ((Attributes
& EFI_MEMORY_RUNTIME
) != 0) {
814 if ((BaseAddress
& EFI_PAGE_MASK
) != 0 || (Length
& EFI_PAGE_MASK
) != 0) {
815 Status
= EFI_INVALID_PARAMETER
;
819 if ((Entry
->Capabilities
& Attributes
) != Attributes
) {
820 Status
= EFI_UNSUPPORTED
;
825 // Set capabilities operation
827 case GCD_SET_CAPABILITIES_MEMORY_OPERATION
:
828 if ((BaseAddress
& EFI_PAGE_MASK
) != 0 || (Length
& EFI_PAGE_MASK
) != 0) {
829 Status
= EFI_INVALID_PARAMETER
;
834 // Current attributes must still be supported with new capabilities
836 if ((Capabilities
& Entry
->Attributes
) != Entry
->Attributes
) {
837 Status
= EFI_UNSUPPORTED
;
842 Link
= Link
->ForwardLink
;
846 // Allocate work space to perform this operation
848 Status
= CoreAllocateGcdMapEntry (&TopEntry
, &BottomEntry
);
849 if (EFI_ERROR (Status
)) {
850 Status
= EFI_OUT_OF_RESOURCES
;
853 ASSERT (TopEntry
!= NULL
&& BottomEntry
!= NULL
);
855 if (Operation
== GCD_SET_ATTRIBUTES_MEMORY_OPERATION
) {
857 // Call CPU Arch Protocol to attempt to set attributes on the range
859 CpuArchAttributes
= ConverToCpuArchAttributes (Attributes
);
860 if (CpuArchAttributes
!= INVALID_CPU_ARCH_ATTRIBUTES
) {
862 Status
= EFI_NOT_AVAILABLE_YET
;
864 Status
= gCpu
->SetMemoryAttributes (
871 if (EFI_ERROR (Status
)) {
872 CoreFreePool (TopEntry
);
873 CoreFreePool (BottomEntry
);
880 // Convert/Insert the list of descriptors from StartLink to EndLink
883 while (Link
!= EndLink
->ForwardLink
) {
884 Entry
= CR (Link
, EFI_GCD_MAP_ENTRY
, Link
, EFI_GCD_MAP_SIGNATURE
);
885 CoreInsertGcdMapEntry (Link
, Entry
, BaseAddress
, Length
, TopEntry
, BottomEntry
);
890 case GCD_ADD_MEMORY_OPERATION
:
891 Entry
->GcdMemoryType
= GcdMemoryType
;
892 if (GcdMemoryType
== EfiGcdMemoryTypeMemoryMappedIo
) {
893 Entry
->Capabilities
= Capabilities
| EFI_MEMORY_RUNTIME
| EFI_MEMORY_PORT_IO
;
895 Entry
->Capabilities
= Capabilities
| EFI_MEMORY_RUNTIME
;
898 case GCD_ADD_IO_OPERATION
:
899 Entry
->GcdIoType
= GcdIoType
;
904 case GCD_FREE_MEMORY_OPERATION
:
905 case GCD_FREE_IO_OPERATION
:
906 Entry
->ImageHandle
= NULL
;
907 Entry
->DeviceHandle
= NULL
;
912 case GCD_REMOVE_MEMORY_OPERATION
:
913 Entry
->GcdMemoryType
= EfiGcdMemoryTypeNonExistent
;
914 Entry
->Capabilities
= 0;
916 case GCD_REMOVE_IO_OPERATION
:
917 Entry
->GcdIoType
= EfiGcdIoTypeNonExistent
;
920 // Set attributes operation
922 case GCD_SET_ATTRIBUTES_MEMORY_OPERATION
:
923 Entry
->Attributes
= Attributes
;
926 // Set capabilities operation
928 case GCD_SET_CAPABILITIES_MEMORY_OPERATION
:
929 Entry
->Capabilities
= Capabilities
;
932 Link
= Link
->ForwardLink
;
938 Status
= CoreCleanupGcdMapEntry (TopEntry
, BottomEntry
, StartLink
, EndLink
, Map
);
941 DEBUG ((DEBUG_GCD
, " Status = %r\n", Status
));
943 if ((Operation
& GCD_MEMORY_SPACE_OPERATION
) != 0) {
944 CoreReleaseGcdMemoryLock ();
945 CoreDumpGcdMemorySpaceMap (FALSE
);
947 if ((Operation
& GCD_IO_SPACE_OPERATION
) != 0) {
948 CoreReleaseGcdIoLock ();
949 CoreDumpGcdIoSpaceMap (FALSE
);
957 Check whether an entry could be used to allocate space.
959 @param Operation Allocate memory or IO
960 @param Entry The entry to be tested
961 @param GcdMemoryType The desired memory type
962 @param GcdIoType The desired IO type
964 @retval EFI_NOT_FOUND The memory type does not match or there's an
965 image handle on the entry.
966 @retval EFI_UNSUPPORTED The operation unsupported.
967 @retval EFI_SUCCESS It's ok for this entry to be used to allocate
972 CoreAllocateSpaceCheckEntry (
974 IN EFI_GCD_MAP_ENTRY
*Entry
,
975 IN EFI_GCD_MEMORY_TYPE GcdMemoryType
,
976 IN EFI_GCD_IO_TYPE GcdIoType
979 if (Entry
->ImageHandle
!= NULL
) {
980 return EFI_NOT_FOUND
;
983 case GCD_ALLOCATE_MEMORY_OPERATION
:
984 if (Entry
->GcdMemoryType
!= GcdMemoryType
) {
985 return EFI_NOT_FOUND
;
988 case GCD_ALLOCATE_IO_OPERATION
:
989 if (Entry
->GcdIoType
!= GcdIoType
) {
990 return EFI_NOT_FOUND
;
994 return EFI_UNSUPPORTED
;
1001 Allocate space on specified address and length.
1003 @param Operation The type of operation (memory or IO)
1004 @param GcdAllocateType The type of allocate operation
1005 @param GcdMemoryType The desired memory type
1006 @param GcdIoType The desired IO type
1007 @param Alignment Align with 2^Alignment
1008 @param Length Length to allocate
1009 @param BaseAddress Base address to allocate
1010 @param ImageHandle The image handle consume the allocated space.
1011 @param DeviceHandle The device handle consume the allocated space.
1013 @retval EFI_INVALID_PARAMETER Invalid parameter.
1014 @retval EFI_NOT_FOUND No descriptor for the desired space exists.
1015 @retval EFI_SUCCESS Space successfully allocated.
1021 IN EFI_GCD_ALLOCATE_TYPE GcdAllocateType
,
1022 IN EFI_GCD_MEMORY_TYPE GcdMemoryType
,
1023 IN EFI_GCD_IO_TYPE GcdIoType
,
1026 IN OUT EFI_PHYSICAL_ADDRESS
*BaseAddress
,
1027 IN EFI_HANDLE ImageHandle
,
1028 IN EFI_HANDLE DeviceHandle OPTIONAL
1032 EFI_PHYSICAL_ADDRESS AlignmentMask
;
1033 EFI_PHYSICAL_ADDRESS MaxAddress
;
1036 LIST_ENTRY
*SubLink
;
1037 EFI_GCD_MAP_ENTRY
*Entry
;
1038 EFI_GCD_MAP_ENTRY
*TopEntry
;
1039 EFI_GCD_MAP_ENTRY
*BottomEntry
;
1040 LIST_ENTRY
*StartLink
;
1041 LIST_ENTRY
*EndLink
;
1045 // Make sure parameters are valid
1047 if ((UINT32
)GcdAllocateType
>= EfiGcdMaxAllocateType
) {
1048 DEBUG ((DEBUG_GCD
, " Status = %r\n", EFI_INVALID_PARAMETER
));
1049 return EFI_INVALID_PARAMETER
;
1051 if ((UINT32
)GcdMemoryType
>= EfiGcdMemoryTypeMaximum
) {
1052 DEBUG ((DEBUG_GCD
, " Status = %r\n", EFI_INVALID_PARAMETER
));
1053 return EFI_INVALID_PARAMETER
;
1055 if ((UINT32
)GcdIoType
>= EfiGcdIoTypeMaximum
) {
1056 DEBUG ((DEBUG_GCD
, " Status = %r\n", EFI_INVALID_PARAMETER
));
1057 return EFI_INVALID_PARAMETER
;
1059 if (BaseAddress
== NULL
) {
1060 DEBUG ((DEBUG_GCD
, " Status = %r\n", EFI_INVALID_PARAMETER
));
1061 return EFI_INVALID_PARAMETER
;
1063 if (ImageHandle
== NULL
) {
1064 DEBUG ((DEBUG_GCD
, " Status = %r\n", EFI_INVALID_PARAMETER
));
1065 return EFI_INVALID_PARAMETER
;
1067 if (Alignment
>= 64) {
1068 DEBUG ((DEBUG_GCD
, " Status = %r\n", EFI_NOT_FOUND
));
1069 return EFI_NOT_FOUND
;
1072 DEBUG ((DEBUG_GCD
, " Status = %r\n", EFI_INVALID_PARAMETER
));
1073 return EFI_INVALID_PARAMETER
;
1077 if ((Operation
& GCD_MEMORY_SPACE_OPERATION
) != 0) {
1078 CoreAcquireGcdMemoryLock ();
1079 Map
= &mGcdMemorySpaceMap
;
1080 } else if ((Operation
& GCD_IO_SPACE_OPERATION
) != 0) {
1081 CoreAcquireGcdIoLock ();
1082 Map
= &mGcdIoSpaceMap
;
1091 // Compute alignment bit mask
1093 AlignmentMask
= LShiftU64 (1, Alignment
) - 1;
1095 if (GcdAllocateType
== EfiGcdAllocateAddress
) {
1097 // Verify that the BaseAddress passed in is aligned correctly
1099 if ((*BaseAddress
& AlignmentMask
) != 0) {
1100 Status
= EFI_NOT_FOUND
;
1105 // Search for the list of descriptors that cover the range BaseAddress to BaseAddress+Length
1107 Status
= CoreSearchGcdMapEntry (*BaseAddress
, Length
, &StartLink
, &EndLink
, Map
);
1108 if (EFI_ERROR (Status
)) {
1109 Status
= EFI_NOT_FOUND
;
1112 ASSERT (StartLink
!= NULL
&& EndLink
!= NULL
);
1115 // Verify that the list of descriptors are unallocated memory matching GcdMemoryType.
1118 while (Link
!= EndLink
->ForwardLink
) {
1119 Entry
= CR (Link
, EFI_GCD_MAP_ENTRY
, Link
, EFI_GCD_MAP_SIGNATURE
);
1120 Link
= Link
->ForwardLink
;
1121 Status
= CoreAllocateSpaceCheckEntry (Operation
, Entry
, GcdMemoryType
, GcdIoType
);
1122 if (EFI_ERROR (Status
)) {
1129 Entry
= CR (Map
->BackLink
, EFI_GCD_MAP_ENTRY
, Link
, EFI_GCD_MAP_SIGNATURE
);
1132 // Compute the maximum address to use in the search algorithm
1134 if (GcdAllocateType
== EfiGcdAllocateMaxAddressSearchBottomUp
||
1135 GcdAllocateType
== EfiGcdAllocateMaxAddressSearchTopDown
) {
1136 MaxAddress
= *BaseAddress
;
1138 MaxAddress
= Entry
->EndAddress
;
1142 // Verify that the list of descriptors are unallocated memory matching GcdMemoryType.
1144 if (GcdAllocateType
== EfiGcdAllocateMaxAddressSearchTopDown
||
1145 GcdAllocateType
== EfiGcdAllocateAnySearchTopDown
) {
1146 Link
= Map
->BackLink
;
1148 Link
= Map
->ForwardLink
;
1150 while (Link
!= Map
) {
1151 Entry
= CR (Link
, EFI_GCD_MAP_ENTRY
, Link
, EFI_GCD_MAP_SIGNATURE
);
1153 if (GcdAllocateType
== EfiGcdAllocateMaxAddressSearchTopDown
||
1154 GcdAllocateType
== EfiGcdAllocateAnySearchTopDown
) {
1155 Link
= Link
->BackLink
;
1157 Link
= Link
->ForwardLink
;
1160 Status
= CoreAllocateSpaceCheckEntry (Operation
, Entry
, GcdMemoryType
, GcdIoType
);
1161 if (EFI_ERROR (Status
)) {
1165 if (GcdAllocateType
== EfiGcdAllocateMaxAddressSearchTopDown
||
1166 GcdAllocateType
== EfiGcdAllocateAnySearchTopDown
) {
1167 if ((Entry
->BaseAddress
+ Length
) > MaxAddress
) {
1170 if (Length
> (Entry
->EndAddress
+ 1)) {
1171 Status
= EFI_NOT_FOUND
;
1174 if (Entry
->EndAddress
> MaxAddress
) {
1175 *BaseAddress
= MaxAddress
;
1177 *BaseAddress
= Entry
->EndAddress
;
1179 *BaseAddress
= (*BaseAddress
+ 1 - Length
) & (~AlignmentMask
);
1181 *BaseAddress
= (Entry
->BaseAddress
+ AlignmentMask
) & (~AlignmentMask
);
1182 if ((*BaseAddress
+ Length
- 1) > MaxAddress
) {
1183 Status
= EFI_NOT_FOUND
;
1189 // Search for the list of descriptors that cover the range BaseAddress to BaseAddress+Length
1191 Status
= CoreSearchGcdMapEntry (*BaseAddress
, Length
, &StartLink
, &EndLink
, Map
);
1192 if (EFI_ERROR (Status
)) {
1193 Status
= EFI_NOT_FOUND
;
1196 ASSERT (StartLink
!= NULL
&& EndLink
!= NULL
);
1200 // Verify that the list of descriptors are unallocated memory matching GcdMemoryType.
1203 SubLink
= StartLink
;
1204 while (SubLink
!= EndLink
->ForwardLink
) {
1205 Entry
= CR (SubLink
, EFI_GCD_MAP_ENTRY
, Link
, EFI_GCD_MAP_SIGNATURE
);
1206 Status
= CoreAllocateSpaceCheckEntry (Operation
, Entry
, GcdMemoryType
, GcdIoType
);
1207 if (EFI_ERROR (Status
)) {
1212 SubLink
= SubLink
->ForwardLink
;
1220 Status
= EFI_NOT_FOUND
;
1225 // Allocate work space to perform this operation
1227 Status
= CoreAllocateGcdMapEntry (&TopEntry
, &BottomEntry
);
1228 if (EFI_ERROR (Status
)) {
1229 Status
= EFI_OUT_OF_RESOURCES
;
1232 ASSERT (TopEntry
!= NULL
&& BottomEntry
!= NULL
);
1235 // Convert/Insert the list of descriptors from StartLink to EndLink
1238 while (Link
!= EndLink
->ForwardLink
) {
1239 Entry
= CR (Link
, EFI_GCD_MAP_ENTRY
, Link
, EFI_GCD_MAP_SIGNATURE
);
1240 CoreInsertGcdMapEntry (Link
, Entry
, *BaseAddress
, Length
, TopEntry
, BottomEntry
);
1241 Entry
->ImageHandle
= ImageHandle
;
1242 Entry
->DeviceHandle
= DeviceHandle
;
1243 Link
= Link
->ForwardLink
;
1249 Status
= CoreCleanupGcdMapEntry (TopEntry
, BottomEntry
, StartLink
, EndLink
, Map
);
1252 DEBUG ((DEBUG_GCD
, " Status = %r", Status
));
1253 if (!EFI_ERROR (Status
)) {
1254 DEBUG ((DEBUG_GCD
, " (BaseAddress = %016lx)", *BaseAddress
));
1256 DEBUG ((DEBUG_GCD
, "\n"));
1258 if ((Operation
& GCD_MEMORY_SPACE_OPERATION
) != 0) {
1259 CoreReleaseGcdMemoryLock ();
1260 CoreDumpGcdMemorySpaceMap (FALSE
);
1262 if ((Operation
& GCD_IO_SPACE_OPERATION
) !=0) {
1263 CoreReleaseGcdIoLock ();
1264 CoreDumpGcdIoSpaceMap (FALSE
);
1272 Add a segment of memory to GCD map.
1274 @param GcdMemoryType Memory type of the segment.
1275 @param BaseAddress Base address of the segment.
1276 @param Length Length of the segment.
1277 @param Capabilities alterable attributes of the segment.
1279 @retval EFI_INVALID_PARAMETER Invalid parameters.
1280 @retval EFI_SUCCESS Successfully add a segment of memory space.
1284 CoreInternalAddMemorySpace (
1285 IN EFI_GCD_MEMORY_TYPE GcdMemoryType
,
1286 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
1288 IN UINT64 Capabilities
1291 DEBUG ((DEBUG_GCD
, "GCD:AddMemorySpace(Base=%016lx,Length=%016lx)\n", BaseAddress
, Length
));
1292 DEBUG ((DEBUG_GCD
, " GcdMemoryType = %a\n", mGcdMemoryTypeNames
[MIN (GcdMemoryType
, EfiGcdMemoryTypeMaximum
)]));
1293 DEBUG ((DEBUG_GCD
, " Capabilities = %016lx\n", Capabilities
));
1296 // Make sure parameters are valid
1298 if (GcdMemoryType
<= EfiGcdMemoryTypeNonExistent
|| GcdMemoryType
>= EfiGcdMemoryTypeMaximum
) {
1299 return EFI_INVALID_PARAMETER
;
1302 return CoreConvertSpace (GCD_ADD_MEMORY_OPERATION
, GcdMemoryType
, (EFI_GCD_IO_TYPE
) 0, BaseAddress
, Length
, Capabilities
, 0);
1306 // GCD Core Services
1310 Allocates nonexistent memory, reserved memory, system memory, or memorymapped
1311 I/O resources from the global coherency domain of the processor.
1313 @param GcdAllocateType The type of allocate operation
1314 @param GcdMemoryType The desired memory type
1315 @param Alignment Align with 2^Alignment
1316 @param Length Length to allocate
1317 @param BaseAddress Base address to allocate
1318 @param ImageHandle The image handle consume the allocated space.
1319 @param DeviceHandle The device handle consume the allocated space.
1321 @retval EFI_INVALID_PARAMETER Invalid parameter.
1322 @retval EFI_NOT_FOUND No descriptor contains the desired space.
1323 @retval EFI_SUCCESS Memory space successfully allocated.
1328 CoreAllocateMemorySpace (
1329 IN EFI_GCD_ALLOCATE_TYPE GcdAllocateType
,
1330 IN EFI_GCD_MEMORY_TYPE GcdMemoryType
,
1333 IN OUT EFI_PHYSICAL_ADDRESS
*BaseAddress
,
1334 IN EFI_HANDLE ImageHandle
,
1335 IN EFI_HANDLE DeviceHandle OPTIONAL
1338 DEBUG ((DEBUG_GCD
, "GCD:AllocateMemorySpace(Base=%016lx,Length=%016lx)\n", *BaseAddress
, Length
));
1339 DEBUG ((DEBUG_GCD
, " GcdAllocateType = %a\n", mGcdAllocationTypeNames
[MIN (GcdAllocateType
, EfiGcdMaxAllocateType
)]));
1340 DEBUG ((DEBUG_GCD
, " GcdMemoryType = %a\n", mGcdMemoryTypeNames
[MIN (GcdMemoryType
, EfiGcdMemoryTypeMaximum
)]));
1341 DEBUG ((DEBUG_GCD
, " Alignment = %016lx\n", LShiftU64 (1, Alignment
)));
1342 DEBUG ((DEBUG_GCD
, " ImageHandle = %p\n", ImageHandle
));
1343 DEBUG ((DEBUG_GCD
, " DeviceHandle = %p\n", DeviceHandle
));
1345 return CoreAllocateSpace (
1346 GCD_ALLOCATE_MEMORY_OPERATION
,
1349 (EFI_GCD_IO_TYPE
) 0,
1360 Adds reserved memory, system memory, or memory-mapped I/O resources to the
1361 global coherency domain of the processor.
1363 @param GcdMemoryType Memory type of the memory space.
1364 @param BaseAddress Base address of the memory space.
1365 @param Length Length of the memory space.
1366 @param Capabilities alterable attributes of the memory space.
1368 @retval EFI_SUCCESS Merged this memory space into GCD map.
1373 CoreAddMemorySpace (
1374 IN EFI_GCD_MEMORY_TYPE GcdMemoryType
,
1375 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
1377 IN UINT64 Capabilities
1381 EFI_PHYSICAL_ADDRESS PageBaseAddress
;
1384 Status
= CoreInternalAddMemorySpace (GcdMemoryType
, BaseAddress
, Length
, Capabilities
);
1386 if (!EFI_ERROR (Status
) && GcdMemoryType
== EfiGcdMemoryTypeSystemMemory
) {
1388 PageBaseAddress
= PageAlignLength (BaseAddress
);
1389 PageLength
= PageAlignLength (BaseAddress
+ Length
- PageBaseAddress
);
1391 Status
= CoreAllocateMemorySpace (
1392 EfiGcdAllocateAddress
,
1397 gDxeCoreImageHandle
,
1401 if (!EFI_ERROR (Status
)) {
1402 CoreAddMemoryDescriptor (
1403 EfiConventionalMemory
,
1405 RShiftU64 (PageLength
, EFI_PAGE_SHIFT
),
1409 for (; PageLength
!= 0; PageLength
-= EFI_PAGE_SIZE
, PageBaseAddress
+= EFI_PAGE_SIZE
) {
1410 Status
= CoreAllocateMemorySpace (
1411 EfiGcdAllocateAddress
,
1416 gDxeCoreImageHandle
,
1420 if (!EFI_ERROR (Status
)) {
1421 CoreAddMemoryDescriptor (
1422 EfiConventionalMemory
,
1436 Frees nonexistent memory, reserved memory, system memory, or memory-mapped
1437 I/O resources from the global coherency domain of the processor.
1439 @param BaseAddress Base address of the memory space.
1440 @param Length Length of the memory space.
1442 @retval EFI_SUCCESS Space successfully freed.
1447 CoreFreeMemorySpace (
1448 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
1452 DEBUG ((DEBUG_GCD
, "GCD:FreeMemorySpace(Base=%016lx,Length=%016lx)\n", BaseAddress
, Length
));
1454 return CoreConvertSpace (GCD_FREE_MEMORY_OPERATION
, (EFI_GCD_MEMORY_TYPE
) 0, (EFI_GCD_IO_TYPE
) 0, BaseAddress
, Length
, 0, 0);
1459 Removes reserved memory, system memory, or memory-mapped I/O resources from
1460 the global coherency domain of the processor.
1462 @param BaseAddress Base address of the memory space.
1463 @param Length Length of the memory space.
1465 @retval EFI_SUCCESS Successfully remove a segment of memory space.
1470 CoreRemoveMemorySpace (
1471 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
1475 DEBUG ((DEBUG_GCD
, "GCD:RemoveMemorySpace(Base=%016lx,Length=%016lx)\n", BaseAddress
, Length
));
1477 return CoreConvertSpace (GCD_REMOVE_MEMORY_OPERATION
, (EFI_GCD_MEMORY_TYPE
) 0, (EFI_GCD_IO_TYPE
) 0, BaseAddress
, Length
, 0, 0);
1482 Build a memory descriptor according to an entry.
1484 @param Descriptor The descriptor to be built
1485 @param Entry According to this entry
1489 BuildMemoryDescriptor (
1490 IN OUT EFI_GCD_MEMORY_SPACE_DESCRIPTOR
*Descriptor
,
1491 IN EFI_GCD_MAP_ENTRY
*Entry
1494 Descriptor
->BaseAddress
= Entry
->BaseAddress
;
1495 Descriptor
->Length
= Entry
->EndAddress
- Entry
->BaseAddress
+ 1;
1496 Descriptor
->Capabilities
= Entry
->Capabilities
;
1497 Descriptor
->Attributes
= Entry
->Attributes
;
1498 Descriptor
->GcdMemoryType
= Entry
->GcdMemoryType
;
1499 Descriptor
->ImageHandle
= Entry
->ImageHandle
;
1500 Descriptor
->DeviceHandle
= Entry
->DeviceHandle
;
1505 Retrieves the descriptor for a memory region containing a specified address.
1507 @param BaseAddress Specified start address
1508 @param Descriptor Specified length
1510 @retval EFI_INVALID_PARAMETER Invalid parameter
1511 @retval EFI_SUCCESS Successfully get memory space descriptor.
1516 CoreGetMemorySpaceDescriptor (
1517 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
1518 OUT EFI_GCD_MEMORY_SPACE_DESCRIPTOR
*Descriptor
1522 LIST_ENTRY
*StartLink
;
1523 LIST_ENTRY
*EndLink
;
1524 EFI_GCD_MAP_ENTRY
*Entry
;
1527 // Make sure parameters are valid
1529 if (Descriptor
== NULL
) {
1530 return EFI_INVALID_PARAMETER
;
1533 CoreAcquireGcdMemoryLock ();
1536 // Search for the list of descriptors that contain BaseAddress
1538 Status
= CoreSearchGcdMapEntry (BaseAddress
, 1, &StartLink
, &EndLink
, &mGcdMemorySpaceMap
);
1539 if (EFI_ERROR (Status
)) {
1540 Status
= EFI_NOT_FOUND
;
1542 ASSERT (StartLink
!= NULL
&& EndLink
!= NULL
);
1544 // Copy the contents of the found descriptor into Descriptor
1546 Entry
= CR (StartLink
, EFI_GCD_MAP_ENTRY
, Link
, EFI_GCD_MAP_SIGNATURE
);
1547 BuildMemoryDescriptor (Descriptor
, Entry
);
1550 CoreReleaseGcdMemoryLock ();
1557 Modifies the attributes for a memory region in the global coherency domain of the
1560 @param BaseAddress Specified start address
1561 @param Length Specified length
1562 @param Attributes Specified attributes
1564 @retval EFI_SUCCESS The attributes were set for the memory region.
1565 @retval EFI_INVALID_PARAMETER Length is zero.
1566 @retval EFI_UNSUPPORTED The processor does not support one or more bytes of the memory
1567 resource range specified by BaseAddress and Length.
1568 @retval EFI_UNSUPPORTED The bit mask of attributes is not support for the memory resource
1569 range specified by BaseAddress and Length.
1570 @retval EFI_ACCESS_DEFINED The attributes for the memory resource range specified by
1571 BaseAddress and Length cannot be modified.
1572 @retval EFI_OUT_OF_RESOURCES There are not enough system resources to modify the attributes of
1573 the memory resource range.
1574 @retval EFI_NOT_AVAILABLE_YET The attributes cannot be set because CPU architectural protocol is
1580 CoreSetMemorySpaceAttributes (
1581 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
1583 IN UINT64 Attributes
1586 DEBUG ((DEBUG_GCD
, "GCD:SetMemorySpaceAttributes(Base=%016lx,Length=%016lx)\n", BaseAddress
, Length
));
1587 DEBUG ((DEBUG_GCD
, " Attributes = %016lx\n", Attributes
));
1589 return CoreConvertSpace (GCD_SET_ATTRIBUTES_MEMORY_OPERATION
, (EFI_GCD_MEMORY_TYPE
) 0, (EFI_GCD_IO_TYPE
) 0, BaseAddress
, Length
, 0, Attributes
);
1594 Modifies the capabilities for a memory region in the global coherency domain of the
1597 @param BaseAddress The physical address that is the start address of a memory region.
1598 @param Length The size in bytes of the memory region.
1599 @param Capabilities The bit mask of capabilities that the memory region supports.
1601 @retval EFI_SUCCESS The capabilities were set for the memory region.
1602 @retval EFI_INVALID_PARAMETER Length is zero.
1603 @retval EFI_UNSUPPORTED The capabilities specified by Capabilities do not include the
1604 memory region attributes currently in use.
1605 @retval EFI_ACCESS_DENIED The capabilities for the memory resource range specified by
1606 BaseAddress and Length cannot be modified.
1607 @retval EFI_OUT_OF_RESOURCES There are not enough system resources to modify the capabilities
1608 of the memory resource range.
1612 CoreSetMemorySpaceCapabilities (
1613 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
1615 IN UINT64 Capabilities
1620 DEBUG ((DEBUG_GCD
, "GCD:CoreSetMemorySpaceCapabilities(Base=%016lx,Length=%016lx)\n", BaseAddress
, Length
));
1621 DEBUG ((DEBUG_GCD
, " Capabilities = %016lx\n", Capabilities
));
1623 Status
= CoreConvertSpace (GCD_SET_CAPABILITIES_MEMORY_OPERATION
, (EFI_GCD_MEMORY_TYPE
) 0, (EFI_GCD_IO_TYPE
) 0, BaseAddress
, Length
, Capabilities
, 0);
1624 if (!EFI_ERROR(Status
)) {
1625 CoreUpdateMemoryAttributes(BaseAddress
, RShiftU64(Length
, EFI_PAGE_SHIFT
), Capabilities
);
1633 Returns a map of the memory resources in the global coherency domain of the
1636 @param NumberOfDescriptors Number of descriptors.
1637 @param MemorySpaceMap Descriptor array
1639 @retval EFI_INVALID_PARAMETER Invalid parameter
1640 @retval EFI_OUT_OF_RESOURCES No enough buffer to allocate
1641 @retval EFI_SUCCESS Successfully get memory space map.
1646 CoreGetMemorySpaceMap (
1647 OUT UINTN
*NumberOfDescriptors
,
1648 OUT EFI_GCD_MEMORY_SPACE_DESCRIPTOR
**MemorySpaceMap
1653 EFI_GCD_MAP_ENTRY
*Entry
;
1654 EFI_GCD_MEMORY_SPACE_DESCRIPTOR
*Descriptor
;
1657 // Make sure parameters are valid
1659 if (NumberOfDescriptors
== NULL
) {
1660 return EFI_INVALID_PARAMETER
;
1662 if (MemorySpaceMap
== NULL
) {
1663 return EFI_INVALID_PARAMETER
;
1666 CoreAcquireGcdMemoryLock ();
1669 // Count the number of descriptors
1671 *NumberOfDescriptors
= CoreCountGcdMapEntry (&mGcdMemorySpaceMap
);
1674 // Allocate the MemorySpaceMap
1676 *MemorySpaceMap
= AllocatePool (*NumberOfDescriptors
* sizeof (EFI_GCD_MEMORY_SPACE_DESCRIPTOR
));
1677 if (*MemorySpaceMap
== NULL
) {
1678 Status
= EFI_OUT_OF_RESOURCES
;
1683 // Fill in the MemorySpaceMap
1685 Descriptor
= *MemorySpaceMap
;
1686 Link
= mGcdMemorySpaceMap
.ForwardLink
;
1687 while (Link
!= &mGcdMemorySpaceMap
) {
1688 Entry
= CR (Link
, EFI_GCD_MAP_ENTRY
, Link
, EFI_GCD_MAP_SIGNATURE
);
1689 BuildMemoryDescriptor (Descriptor
, Entry
);
1691 Link
= Link
->ForwardLink
;
1693 Status
= EFI_SUCCESS
;
1696 CoreReleaseGcdMemoryLock ();
1702 Adds reserved I/O or I/O resources to the global coherency domain of the processor.
1704 @param GcdIoType IO type of the segment.
1705 @param BaseAddress Base address of the segment.
1706 @param Length Length of the segment.
1708 @retval EFI_SUCCESS Merged this segment into GCD map.
1709 @retval EFI_INVALID_PARAMETER Parameter not valid
1715 IN EFI_GCD_IO_TYPE GcdIoType
,
1716 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
1720 DEBUG ((DEBUG_GCD
, "GCD:AddIoSpace(Base=%016lx,Length=%016lx)\n", BaseAddress
, Length
));
1721 DEBUG ((DEBUG_GCD
, " GcdIoType = %a\n", mGcdIoTypeNames
[MIN (GcdIoType
, EfiGcdIoTypeMaximum
)]));
1724 // Make sure parameters are valid
1726 if (GcdIoType
<= EfiGcdIoTypeNonExistent
|| GcdIoType
>= EfiGcdIoTypeMaximum
) {
1727 return EFI_INVALID_PARAMETER
;
1729 return CoreConvertSpace (GCD_ADD_IO_OPERATION
, (EFI_GCD_MEMORY_TYPE
) 0, GcdIoType
, BaseAddress
, Length
, 0, 0);
1734 Allocates nonexistent I/O, reserved I/O, or I/O resources from the global coherency
1735 domain of the processor.
1737 @param GcdAllocateType The type of allocate operation
1738 @param GcdIoType The desired IO type
1739 @param Alignment Align with 2^Alignment
1740 @param Length Length to allocate
1741 @param BaseAddress Base address to allocate
1742 @param ImageHandle The image handle consume the allocated space.
1743 @param DeviceHandle The device handle consume the allocated space.
1745 @retval EFI_INVALID_PARAMETER Invalid parameter.
1746 @retval EFI_NOT_FOUND No descriptor contains the desired space.
1747 @retval EFI_SUCCESS IO space successfully allocated.
1752 CoreAllocateIoSpace (
1753 IN EFI_GCD_ALLOCATE_TYPE GcdAllocateType
,
1754 IN EFI_GCD_IO_TYPE GcdIoType
,
1757 IN OUT EFI_PHYSICAL_ADDRESS
*BaseAddress
,
1758 IN EFI_HANDLE ImageHandle
,
1759 IN EFI_HANDLE DeviceHandle OPTIONAL
1762 DEBUG ((DEBUG_GCD
, "GCD:AllocateIoSpace(Base=%016lx,Length=%016lx)\n", *BaseAddress
, Length
));
1763 DEBUG ((DEBUG_GCD
, " GcdAllocateType = %a\n", mGcdAllocationTypeNames
[MIN (GcdAllocateType
, EfiGcdMaxAllocateType
)]));
1764 DEBUG ((DEBUG_GCD
, " GcdIoType = %a\n", mGcdIoTypeNames
[MIN (GcdIoType
, EfiGcdIoTypeMaximum
)]));
1765 DEBUG ((DEBUG_GCD
, " Alignment = %016lx\n", LShiftU64 (1, Alignment
)));
1766 DEBUG ((DEBUG_GCD
, " ImageHandle = %p\n", ImageHandle
));
1767 DEBUG ((DEBUG_GCD
, " DeviceHandle = %p\n", DeviceHandle
));
1769 return CoreAllocateSpace (
1770 GCD_ALLOCATE_IO_OPERATION
,
1772 (EFI_GCD_MEMORY_TYPE
) 0,
1784 Frees nonexistent I/O, reserved I/O, or I/O resources from the global coherency
1785 domain of the processor.
1787 @param BaseAddress Base address of the segment.
1788 @param Length Length of the segment.
1790 @retval EFI_SUCCESS Space successfully freed.
1796 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
1800 DEBUG ((DEBUG_GCD
, "GCD:FreeIoSpace(Base=%016lx,Length=%016lx)\n", BaseAddress
, Length
));
1802 return CoreConvertSpace (GCD_FREE_IO_OPERATION
, (EFI_GCD_MEMORY_TYPE
) 0, (EFI_GCD_IO_TYPE
) 0, BaseAddress
, Length
, 0, 0);
1807 Removes reserved I/O or I/O resources from the global coherency domain of the
1810 @param BaseAddress Base address of the segment.
1811 @param Length Length of the segment.
1813 @retval EFI_SUCCESS Successfully removed a segment of IO space.
1819 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
1823 DEBUG ((DEBUG_GCD
, "GCD:RemoveIoSpace(Base=%016lx,Length=%016lx)\n", BaseAddress
, Length
));
1825 return CoreConvertSpace (GCD_REMOVE_IO_OPERATION
, (EFI_GCD_MEMORY_TYPE
) 0, (EFI_GCD_IO_TYPE
) 0, BaseAddress
, Length
, 0, 0);
1830 Build a IO descriptor according to an entry.
1832 @param Descriptor The descriptor to be built
1833 @param Entry According to this entry
1838 IN EFI_GCD_IO_SPACE_DESCRIPTOR
*Descriptor
,
1839 IN EFI_GCD_MAP_ENTRY
*Entry
1842 Descriptor
->BaseAddress
= Entry
->BaseAddress
;
1843 Descriptor
->Length
= Entry
->EndAddress
- Entry
->BaseAddress
+ 1;
1844 Descriptor
->GcdIoType
= Entry
->GcdIoType
;
1845 Descriptor
->ImageHandle
= Entry
->ImageHandle
;
1846 Descriptor
->DeviceHandle
= Entry
->DeviceHandle
;
1851 Retrieves the descriptor for an I/O region containing a specified address.
1853 @param BaseAddress Specified start address
1854 @param Descriptor Specified length
1856 @retval EFI_INVALID_PARAMETER Descriptor is NULL.
1857 @retval EFI_SUCCESS Successfully get the IO space descriptor.
1862 CoreGetIoSpaceDescriptor (
1863 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
1864 OUT EFI_GCD_IO_SPACE_DESCRIPTOR
*Descriptor
1868 LIST_ENTRY
*StartLink
;
1869 LIST_ENTRY
*EndLink
;
1870 EFI_GCD_MAP_ENTRY
*Entry
;
1873 // Make sure parameters are valid
1875 if (Descriptor
== NULL
) {
1876 return EFI_INVALID_PARAMETER
;
1879 CoreAcquireGcdIoLock ();
1882 // Search for the list of descriptors that contain BaseAddress
1884 Status
= CoreSearchGcdMapEntry (BaseAddress
, 1, &StartLink
, &EndLink
, &mGcdIoSpaceMap
);
1885 if (EFI_ERROR (Status
)) {
1886 Status
= EFI_NOT_FOUND
;
1888 ASSERT (StartLink
!= NULL
&& EndLink
!= NULL
);
1890 // Copy the contents of the found descriptor into Descriptor
1892 Entry
= CR (StartLink
, EFI_GCD_MAP_ENTRY
, Link
, EFI_GCD_MAP_SIGNATURE
);
1893 BuildIoDescriptor (Descriptor
, Entry
);
1896 CoreReleaseGcdIoLock ();
1903 Returns a map of the I/O resources in the global coherency domain of the processor.
1905 @param NumberOfDescriptors Number of descriptors.
1906 @param IoSpaceMap Descriptor array
1908 @retval EFI_INVALID_PARAMETER Invalid parameter
1909 @retval EFI_OUT_OF_RESOURCES No enough buffer to allocate
1910 @retval EFI_SUCCESS Successfully get IO space map.
1916 OUT UINTN
*NumberOfDescriptors
,
1917 OUT EFI_GCD_IO_SPACE_DESCRIPTOR
**IoSpaceMap
1922 EFI_GCD_MAP_ENTRY
*Entry
;
1923 EFI_GCD_IO_SPACE_DESCRIPTOR
*Descriptor
;
1926 // Make sure parameters are valid
1928 if (NumberOfDescriptors
== NULL
) {
1929 return EFI_INVALID_PARAMETER
;
1931 if (IoSpaceMap
== NULL
) {
1932 return EFI_INVALID_PARAMETER
;
1935 CoreAcquireGcdIoLock ();
1938 // Count the number of descriptors
1940 *NumberOfDescriptors
= CoreCountGcdMapEntry (&mGcdIoSpaceMap
);
1943 // Allocate the IoSpaceMap
1945 *IoSpaceMap
= AllocatePool (*NumberOfDescriptors
* sizeof (EFI_GCD_IO_SPACE_DESCRIPTOR
));
1946 if (*IoSpaceMap
== NULL
) {
1947 Status
= EFI_OUT_OF_RESOURCES
;
1952 // Fill in the IoSpaceMap
1954 Descriptor
= *IoSpaceMap
;
1955 Link
= mGcdIoSpaceMap
.ForwardLink
;
1956 while (Link
!= &mGcdIoSpaceMap
) {
1957 Entry
= CR (Link
, EFI_GCD_MAP_ENTRY
, Link
, EFI_GCD_MAP_SIGNATURE
);
1958 BuildIoDescriptor (Descriptor
, Entry
);
1960 Link
= Link
->ForwardLink
;
1962 Status
= EFI_SUCCESS
;
1965 CoreReleaseGcdIoLock ();
1971 Converts a Resource Descriptor HOB attributes mask to an EFI Memory Descriptor
1974 @param GcdMemoryType Type of resource in the GCD memory map.
1975 @param Attributes The attribute mask in the Resource Descriptor
1978 @return The capabilities mask for an EFI Memory Descriptor.
1982 CoreConvertResourceDescriptorHobAttributesToCapabilities (
1983 EFI_GCD_MEMORY_TYPE GcdMemoryType
,
1987 UINT64 Capabilities
;
1988 GCD_ATTRIBUTE_CONVERSION_ENTRY
*Conversion
;
1991 // Convert the Resource HOB Attributes to an EFI Memory Capabilities mask
1993 for (Capabilities
= 0, Conversion
= mAttributeConversionTable
; Conversion
->Attribute
!= 0; Conversion
++) {
1994 if (Conversion
->Memory
|| (GcdMemoryType
!= EfiGcdMemoryTypeSystemMemory
)) {
1995 if (Attributes
& Conversion
->Attribute
) {
1996 Capabilities
|= Conversion
->Capability
;
2001 return Capabilities
;
2006 External function. Initializes memory services based on the memory
2007 descriptor HOBs. This function is responsible for priming the memory
2008 map, so memory allocations and resource allocations can be made.
2009 The first part of this function can not depend on any memory services
2010 until at least one memory descriptor is provided to the memory services.
2012 @param HobStart The start address of the HOB.
2013 @param MemoryBaseAddress Start address of memory region found to init DXE
2015 @param MemoryLength Length of memory region found to init DXE core.
2017 @retval EFI_SUCCESS Memory services successfully initialized.
2021 CoreInitializeMemoryServices (
2023 OUT EFI_PHYSICAL_ADDRESS
*MemoryBaseAddress
,
2024 OUT UINT64
*MemoryLength
2027 EFI_PEI_HOB_POINTERS Hob
;
2028 EFI_MEMORY_TYPE_INFORMATION
*EfiMemoryTypeInformation
;
2031 EFI_HOB_HANDOFF_INFO_TABLE
*PhitHob
;
2032 EFI_HOB_RESOURCE_DESCRIPTOR
*ResourceHob
;
2033 EFI_HOB_RESOURCE_DESCRIPTOR
*PhitResourceHob
;
2034 EFI_PHYSICAL_ADDRESS BaseAddress
;
2037 UINT64 Capabilities
;
2038 EFI_PHYSICAL_ADDRESS MaxMemoryBaseAddress
;
2039 UINT64 MaxMemoryLength
;
2040 UINT64 MaxMemoryAttributes
;
2041 EFI_PHYSICAL_ADDRESS TestedMemoryBaseAddress
;
2042 UINT64 TestedMemoryLength
;
2043 EFI_PHYSICAL_ADDRESS HighAddress
;
2044 EFI_HOB_GUID_TYPE
*GuidHob
;
2045 UINT32 ReservedCodePageNumber
;
2048 // Point at the first HOB. This must be the PHIT HOB.
2050 Hob
.Raw
= *HobStart
;
2051 ASSERT (GET_HOB_TYPE (Hob
) == EFI_HOB_TYPE_HANDOFF
);
2054 // Initialize the spin locks and maps in the memory services.
2055 // Also fill in the memory services into the EFI Boot Services Table
2057 CoreInitializePool ();
2060 // Initialize Local Variables
2062 PhitResourceHob
= NULL
;
2067 MaxMemoryBaseAddress
= 0;
2068 MaxMemoryLength
= 0;
2069 MaxMemoryAttributes
= 0;
2072 // Cache the PHIT HOB for later use
2074 PhitHob
= Hob
.HandoffInformationTable
;
2076 if (PcdGet64(PcdLoadModuleAtFixAddressEnable
) != 0) {
2077 ReservedCodePageNumber
= PcdGet32(PcdLoadFixAddressRuntimeCodePageNumber
);
2078 ReservedCodePageNumber
+= PcdGet32(PcdLoadFixAddressBootTimeCodePageNumber
);
2081 // cache the Top address for loading modules at Fixed Address
2083 gLoadModuleAtFixAddressConfigurationTable
.DxeCodeTopAddress
= PhitHob
->EfiMemoryTop
2084 + EFI_PAGES_TO_SIZE(ReservedCodePageNumber
);
2087 // See if a Memory Type Information HOB is available
2089 GuidHob
= GetFirstGuidHob (&gEfiMemoryTypeInformationGuid
);
2090 if (GuidHob
!= NULL
) {
2091 EfiMemoryTypeInformation
= GET_GUID_HOB_DATA (GuidHob
);
2092 DataSize
= GET_GUID_HOB_DATA_SIZE (GuidHob
);
2093 if (EfiMemoryTypeInformation
!= NULL
&& DataSize
> 0 && DataSize
<= (EfiMaxMemoryType
+ 1) * sizeof (EFI_MEMORY_TYPE_INFORMATION
)) {
2094 CopyMem (&gMemoryTypeInformation
, EfiMemoryTypeInformation
, DataSize
);
2099 // Find the Resource Descriptor HOB that contains PHIT range EfiFreeMemoryBottom..EfiFreeMemoryTop
2103 for (Hob
.Raw
= *HobStart
; !END_OF_HOB_LIST(Hob
); Hob
.Raw
= GET_NEXT_HOB(Hob
)) {
2105 // Skip all HOBs except Resource Descriptor HOBs
2107 if (GET_HOB_TYPE (Hob
) != EFI_HOB_TYPE_RESOURCE_DESCRIPTOR
) {
2112 // Skip Resource Descriptor HOBs that do not describe tested system memory
2114 ResourceHob
= Hob
.ResourceDescriptor
;
2115 if (ResourceHob
->ResourceType
!= EFI_RESOURCE_SYSTEM_MEMORY
) {
2118 if ((ResourceHob
->ResourceAttribute
& MEMORY_ATTRIBUTE_MASK
) != TESTED_MEMORY_ATTRIBUTES
) {
2123 // Skip Resource Descriptor HOBs that do not contain the PHIT range EfiFreeMemoryBottom..EfiFreeMemoryTop
2125 if (PhitHob
->EfiFreeMemoryBottom
< ResourceHob
->PhysicalStart
) {
2128 if (PhitHob
->EfiFreeMemoryTop
> (ResourceHob
->PhysicalStart
+ ResourceHob
->ResourceLength
)) {
2133 // Cache the resource descriptor HOB for the memory region described by the PHIT HOB
2135 PhitResourceHob
= ResourceHob
;
2139 // Compute range between PHIT EfiFreeMemoryTop and the end of the Resource Descriptor HOB
2141 Attributes
= PhitResourceHob
->ResourceAttribute
;
2142 BaseAddress
= PageAlignAddress (PhitHob
->EfiMemoryTop
);
2143 Length
= PageAlignLength (ResourceHob
->PhysicalStart
+ ResourceHob
->ResourceLength
- BaseAddress
);
2144 if (Length
< MINIMUM_INITIAL_MEMORY_SIZE
) {
2146 // If that range is not large enough to intialize the DXE Core, then
2147 // Compute range between PHIT EfiFreeMemoryBottom and PHIT EfiFreeMemoryTop
2149 BaseAddress
= PageAlignAddress (PhitHob
->EfiFreeMemoryBottom
);
2150 Length
= PageAlignLength (PhitHob
->EfiFreeMemoryTop
- BaseAddress
);
2151 if (Length
< MINIMUM_INITIAL_MEMORY_SIZE
) {
2153 // If that range is not large enough to intialize the DXE Core, then
2154 // Compute range between the start of the Resource Descriptor HOB and the start of the HOB List
2156 BaseAddress
= PageAlignAddress (ResourceHob
->PhysicalStart
);
2157 Length
= PageAlignLength ((UINT64
)((UINTN
)*HobStart
- BaseAddress
));
2164 // Assert if a resource descriptor HOB for the memory region described by the PHIT was not found
2169 // Search all the resource descriptor HOBs from the highest possible addresses down for a memory
2170 // region that is big enough to initialize the DXE core. Always skip the PHIT Resource HOB.
2171 // The max address must be within the physically addressible range for the processor.
2173 HighAddress
= MAX_ADDRESS
;
2174 for (Hob
.Raw
= *HobStart
; !END_OF_HOB_LIST(Hob
); Hob
.Raw
= GET_NEXT_HOB(Hob
)) {
2176 // Skip the Resource Descriptor HOB that contains the PHIT
2178 if (Hob
.ResourceDescriptor
== PhitResourceHob
) {
2182 // Skip all HOBs except Resource Descriptor HOBs
2184 if (GET_HOB_TYPE (Hob
) != EFI_HOB_TYPE_RESOURCE_DESCRIPTOR
) {
2189 // Skip Resource Descriptor HOBs that do not describe tested system memory below MAX_ADDRESS
2191 ResourceHob
= Hob
.ResourceDescriptor
;
2192 if (ResourceHob
->ResourceType
!= EFI_RESOURCE_SYSTEM_MEMORY
) {
2195 if ((ResourceHob
->ResourceAttribute
& MEMORY_ATTRIBUTE_MASK
) != TESTED_MEMORY_ATTRIBUTES
) {
2198 if ((ResourceHob
->PhysicalStart
+ ResourceHob
->ResourceLength
) > (EFI_PHYSICAL_ADDRESS
)MAX_ADDRESS
) {
2203 // Skip Resource Descriptor HOBs that are below a previously found Resource Descriptor HOB
2205 if (HighAddress
!= (EFI_PHYSICAL_ADDRESS
)MAX_ADDRESS
&& ResourceHob
->PhysicalStart
<= HighAddress
) {
2210 // Skip Resource Descriptor HOBs that are not large enough to initilize the DXE Core
2212 TestedMemoryBaseAddress
= PageAlignAddress (ResourceHob
->PhysicalStart
);
2213 TestedMemoryLength
= PageAlignLength (ResourceHob
->PhysicalStart
+ ResourceHob
->ResourceLength
- TestedMemoryBaseAddress
);
2214 if (TestedMemoryLength
< MINIMUM_INITIAL_MEMORY_SIZE
) {
2219 // Save the Resource Descriptor HOB context that is large enough to initilize the DXE Core
2221 MaxMemoryBaseAddress
= TestedMemoryBaseAddress
;
2222 MaxMemoryLength
= TestedMemoryLength
;
2223 MaxMemoryAttributes
= ResourceHob
->ResourceAttribute
;
2224 HighAddress
= ResourceHob
->PhysicalStart
;
2228 // If Length is not large enough to initialize the DXE Core or a Resource
2229 // Descriptor HOB was found above the PHIT HOB that is large enough to initialize
2230 // the DXE Core, then use the range described by the Resource Descriptor
2231 // HOB that was found above the PHIT HOB.
2233 if ((Length
< MINIMUM_INITIAL_MEMORY_SIZE
) ||
2234 (MaxMemoryBaseAddress
> BaseAddress
&& MaxMemoryLength
>= MINIMUM_INITIAL_MEMORY_SIZE
)) {
2235 BaseAddress
= MaxMemoryBaseAddress
;
2236 Length
= MaxMemoryLength
;
2237 Attributes
= MaxMemoryAttributes
;
2241 // If no memory regions are found that are big enough to initialize the DXE core, then ASSERT().
2243 ASSERT (Length
>= MINIMUM_INITIAL_MEMORY_SIZE
);
2246 // Convert the Resource HOB Attributes to an EFI Memory Capabilities mask
2248 Capabilities
= CoreConvertResourceDescriptorHobAttributesToCapabilities (EfiGcdMemoryTypeSystemMemory
, Attributes
);
2251 // Declare the very first memory region, so the EFI Memory Services are available.
2253 CoreAddMemoryDescriptor (
2254 EfiConventionalMemory
,
2256 RShiftU64 (Length
, EFI_PAGE_SHIFT
),
2260 *MemoryBaseAddress
= BaseAddress
;
2261 *MemoryLength
= Length
;
2268 External function. Initializes the GCD and memory services based on the memory
2269 descriptor HOBs. This function is responsible for priming the GCD map and the
2270 memory map, so memory allocations and resource allocations can be made. The
2271 HobStart will be relocated to a pool buffer.
2273 @param HobStart The start address of the HOB
2274 @param MemoryBaseAddress Start address of memory region found to init DXE
2276 @param MemoryLength Length of memory region found to init DXE core.
2278 @retval EFI_SUCCESS GCD services successfully initialized.
2282 CoreInitializeGcdServices (
2283 IN OUT VOID
**HobStart
,
2284 IN EFI_PHYSICAL_ADDRESS MemoryBaseAddress
,
2285 IN UINT64 MemoryLength
2288 EFI_PEI_HOB_POINTERS Hob
;
2290 EFI_HOB_HANDOFF_INFO_TABLE
*PhitHob
;
2291 UINT8 SizeOfMemorySpace
;
2292 UINT8 SizeOfIoSpace
;
2293 EFI_HOB_RESOURCE_DESCRIPTOR
*ResourceHob
;
2294 EFI_PHYSICAL_ADDRESS BaseAddress
;
2297 EFI_GCD_MAP_ENTRY
*Entry
;
2298 EFI_GCD_MEMORY_TYPE GcdMemoryType
;
2299 EFI_GCD_IO_TYPE GcdIoType
;
2300 EFI_GCD_MEMORY_SPACE_DESCRIPTOR Descriptor
;
2301 EFI_HOB_MEMORY_ALLOCATION
*MemoryHob
;
2302 EFI_HOB_FIRMWARE_VOLUME
*FirmwareVolumeHob
;
2303 UINTN NumberOfDescriptors
;
2304 EFI_GCD_MEMORY_SPACE_DESCRIPTOR
*MemorySpaceMap
;
2306 UINT64 Capabilities
;
2307 EFI_HOB_CPU
* CpuHob
;
2310 // Cache the PHIT HOB for later use
2312 PhitHob
= (EFI_HOB_HANDOFF_INFO_TABLE
*)(*HobStart
);
2315 // Get the number of address lines in the I/O and Memory space for the CPU
2317 CpuHob
= GetFirstHob (EFI_HOB_TYPE_CPU
);
2318 ASSERT (CpuHob
!= NULL
);
2319 SizeOfMemorySpace
= CpuHob
->SizeOfMemorySpace
;
2320 SizeOfIoSpace
= CpuHob
->SizeOfIoSpace
;
2323 // Initialize the GCD Memory Space Map
2325 Entry
= AllocateCopyPool (sizeof (EFI_GCD_MAP_ENTRY
), &mGcdMemorySpaceMapEntryTemplate
);
2326 ASSERT (Entry
!= NULL
);
2328 Entry
->EndAddress
= LShiftU64 (1, SizeOfMemorySpace
) - 1;
2330 InsertHeadList (&mGcdMemorySpaceMap
, &Entry
->Link
);
2332 CoreDumpGcdMemorySpaceMap (TRUE
);
2335 // Initialize the GCD I/O Space Map
2337 Entry
= AllocateCopyPool (sizeof (EFI_GCD_MAP_ENTRY
), &mGcdIoSpaceMapEntryTemplate
);
2338 ASSERT (Entry
!= NULL
);
2340 Entry
->EndAddress
= LShiftU64 (1, SizeOfIoSpace
) - 1;
2342 InsertHeadList (&mGcdIoSpaceMap
, &Entry
->Link
);
2344 CoreDumpGcdIoSpaceMap (TRUE
);
2347 // Walk the HOB list and add all resource descriptors to the GCD
2349 for (Hob
.Raw
= *HobStart
; !END_OF_HOB_LIST(Hob
); Hob
.Raw
= GET_NEXT_HOB(Hob
)) {
2351 GcdMemoryType
= EfiGcdMemoryTypeNonExistent
;
2352 GcdIoType
= EfiGcdIoTypeNonExistent
;
2354 if (GET_HOB_TYPE (Hob
) == EFI_HOB_TYPE_RESOURCE_DESCRIPTOR
) {
2356 ResourceHob
= Hob
.ResourceDescriptor
;
2358 switch (ResourceHob
->ResourceType
) {
2359 case EFI_RESOURCE_SYSTEM_MEMORY
:
2360 if ((ResourceHob
->ResourceAttribute
& MEMORY_ATTRIBUTE_MASK
) == TESTED_MEMORY_ATTRIBUTES
) {
2361 GcdMemoryType
= EfiGcdMemoryTypeSystemMemory
;
2363 if ((ResourceHob
->ResourceAttribute
& MEMORY_ATTRIBUTE_MASK
) == INITIALIZED_MEMORY_ATTRIBUTES
) {
2364 GcdMemoryType
= EfiGcdMemoryTypeReserved
;
2366 if ((ResourceHob
->ResourceAttribute
& MEMORY_ATTRIBUTE_MASK
) == PRESENT_MEMORY_ATTRIBUTES
) {
2367 GcdMemoryType
= EfiGcdMemoryTypeReserved
;
2369 if ((ResourceHob
->ResourceAttribute
& EFI_RESOURCE_ATTRIBUTE_PERSISTENT
) == EFI_RESOURCE_ATTRIBUTE_PERSISTENT
) {
2370 GcdMemoryType
= EfiGcdMemoryTypePersistentMemory
;
2373 case EFI_RESOURCE_MEMORY_MAPPED_IO
:
2374 case EFI_RESOURCE_FIRMWARE_DEVICE
:
2375 GcdMemoryType
= EfiGcdMemoryTypeMemoryMappedIo
;
2377 case EFI_RESOURCE_MEMORY_MAPPED_IO_PORT
:
2378 case EFI_RESOURCE_MEMORY_RESERVED
:
2379 GcdMemoryType
= EfiGcdMemoryTypeReserved
;
2381 case EFI_RESOURCE_IO
:
2382 GcdIoType
= EfiGcdIoTypeIo
;
2384 case EFI_RESOURCE_IO_RESERVED
:
2385 GcdIoType
= EfiGcdIoTypeReserved
;
2389 if (GcdMemoryType
!= EfiGcdMemoryTypeNonExistent
) {
2391 // Validate the Resource HOB Attributes
2393 CoreValidateResourceDescriptorHobAttributes (ResourceHob
->ResourceAttribute
);
2396 // Convert the Resource HOB Attributes to an EFI Memory Capabilities mask
2398 Capabilities
= CoreConvertResourceDescriptorHobAttributesToCapabilities (
2400 ResourceHob
->ResourceAttribute
2403 Status
= CoreInternalAddMemorySpace (
2405 ResourceHob
->PhysicalStart
,
2406 ResourceHob
->ResourceLength
,
2411 if (GcdIoType
!= EfiGcdIoTypeNonExistent
) {
2412 Status
= CoreAddIoSpace (
2414 ResourceHob
->PhysicalStart
,
2415 ResourceHob
->ResourceLength
2422 // Allocate first memory region from the GCD by the DXE core
2424 Status
= CoreAllocateMemorySpace (
2425 EfiGcdAllocateAddress
,
2426 EfiGcdMemoryTypeSystemMemory
,
2430 gDxeCoreImageHandle
,
2435 // Walk the HOB list and allocate all memory space that is consumed by memory allocation HOBs,
2436 // and Firmware Volume HOBs. Also update the EFI Memory Map with the memory allocation HOBs.
2438 for (Hob
.Raw
= *HobStart
; !END_OF_HOB_LIST(Hob
); Hob
.Raw
= GET_NEXT_HOB(Hob
)) {
2439 if (GET_HOB_TYPE (Hob
) == EFI_HOB_TYPE_MEMORY_ALLOCATION
) {
2440 MemoryHob
= Hob
.MemoryAllocation
;
2441 BaseAddress
= MemoryHob
->AllocDescriptor
.MemoryBaseAddress
;
2442 Status
= CoreGetMemorySpaceDescriptor (BaseAddress
, &Descriptor
);
2443 if (!EFI_ERROR (Status
)) {
2444 Status
= CoreAllocateMemorySpace (
2445 EfiGcdAllocateAddress
,
2446 Descriptor
.GcdMemoryType
,
2448 MemoryHob
->AllocDescriptor
.MemoryLength
,
2450 gDxeCoreImageHandle
,
2453 if (!EFI_ERROR (Status
) && Descriptor
.GcdMemoryType
== EfiGcdMemoryTypeSystemMemory
) {
2454 CoreAddMemoryDescriptor (
2455 MemoryHob
->AllocDescriptor
.MemoryType
,
2456 MemoryHob
->AllocDescriptor
.MemoryBaseAddress
,
2457 RShiftU64 (MemoryHob
->AllocDescriptor
.MemoryLength
, EFI_PAGE_SHIFT
),
2458 Descriptor
.Capabilities
& (~EFI_MEMORY_RUNTIME
)
2464 if (GET_HOB_TYPE (Hob
) == EFI_HOB_TYPE_FV
) {
2465 FirmwareVolumeHob
= Hob
.FirmwareVolume
;
2466 BaseAddress
= FirmwareVolumeHob
->BaseAddress
;
2467 Status
= CoreAllocateMemorySpace (
2468 EfiGcdAllocateAddress
,
2469 EfiGcdMemoryTypeMemoryMappedIo
,
2471 FirmwareVolumeHob
->Length
,
2473 gDxeCoreImageHandle
,
2480 // Relocate HOB List to an allocated pool buffer.
2482 NewHobList
= AllocateCopyPool (
2483 (UINTN
)PhitHob
->EfiFreeMemoryBottom
- (UINTN
)(*HobStart
),
2486 ASSERT (NewHobList
!= NULL
);
2488 *HobStart
= NewHobList
;
2489 gHobList
= NewHobList
;
2492 // Add and allocate the remaining unallocated system memory to the memory services.
2494 Status
= CoreGetMemorySpaceMap (&NumberOfDescriptors
, &MemorySpaceMap
);
2495 ASSERT (Status
== EFI_SUCCESS
);
2497 for (Index
= 0; Index
< NumberOfDescriptors
; Index
++) {
2498 if (MemorySpaceMap
[Index
].GcdMemoryType
== EfiGcdMemoryTypeSystemMemory
) {
2499 if (MemorySpaceMap
[Index
].ImageHandle
== NULL
) {
2500 BaseAddress
= PageAlignAddress (MemorySpaceMap
[Index
].BaseAddress
);
2501 Length
= PageAlignLength (MemorySpaceMap
[Index
].BaseAddress
+ MemorySpaceMap
[Index
].Length
- BaseAddress
);
2502 if (Length
== 0 || MemorySpaceMap
[Index
].BaseAddress
+ MemorySpaceMap
[Index
].Length
< BaseAddress
) {
2505 CoreAddMemoryDescriptor (
2506 EfiConventionalMemory
,
2508 RShiftU64 (Length
, EFI_PAGE_SHIFT
),
2509 MemorySpaceMap
[Index
].Capabilities
& (~EFI_MEMORY_RUNTIME
)
2511 Status
= CoreAllocateMemorySpace (
2512 EfiGcdAllocateAddress
,
2513 EfiGcdMemoryTypeSystemMemory
,
2517 gDxeCoreImageHandle
,
2523 CoreFreePool (MemorySpaceMap
);