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_16_BIT_IO | \
29 EFI_RESOURCE_ATTRIBUTE_32_BIT_IO | \
30 EFI_RESOURCE_ATTRIBUTE_64_BIT_IO | \
31 EFI_RESOURCE_ATTRIBUTE_PERSISTENT )
33 #define TESTED_MEMORY_ATTRIBUTES (EFI_RESOURCE_ATTRIBUTE_PRESENT | \
34 EFI_RESOURCE_ATTRIBUTE_INITIALIZED | \
35 EFI_RESOURCE_ATTRIBUTE_TESTED )
37 #define INITIALIZED_MEMORY_ATTRIBUTES (EFI_RESOURCE_ATTRIBUTE_PRESENT | \
38 EFI_RESOURCE_ATTRIBUTE_INITIALIZED )
40 #define PRESENT_MEMORY_ATTRIBUTES (EFI_RESOURCE_ATTRIBUTE_PRESENT)
42 #define INVALID_CPU_ARCH_ATTRIBUTES 0xffffffff
47 EFI_LOCK mGcdMemorySpaceLock
= EFI_INITIALIZE_LOCK_VARIABLE (TPL_NOTIFY
);
48 EFI_LOCK mGcdIoSpaceLock
= EFI_INITIALIZE_LOCK_VARIABLE (TPL_NOTIFY
);
49 LIST_ENTRY mGcdMemorySpaceMap
= INITIALIZE_LIST_HEAD_VARIABLE (mGcdMemorySpaceMap
);
50 LIST_ENTRY mGcdIoSpaceMap
= INITIALIZE_LIST_HEAD_VARIABLE (mGcdIoSpaceMap
);
52 EFI_GCD_MAP_ENTRY mGcdMemorySpaceMapEntryTemplate
= {
53 EFI_GCD_MAP_SIGNATURE
,
62 EfiGcdMemoryTypeNonExistent
,
68 EFI_GCD_MAP_ENTRY mGcdIoSpaceMapEntryTemplate
= {
69 EFI_GCD_MAP_SIGNATURE
,
78 (EFI_GCD_MEMORY_TYPE
) 0,
79 EfiGcdIoTypeNonExistent
,
84 GCD_ATTRIBUTE_CONVERSION_ENTRY mAttributeConversionTable
[] = {
85 { EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE
, EFI_MEMORY_UC
, TRUE
},
86 { EFI_RESOURCE_ATTRIBUTE_UNCACHED_EXPORTED
, EFI_MEMORY_UCE
, TRUE
},
87 { EFI_RESOURCE_ATTRIBUTE_WRITE_COMBINEABLE
, EFI_MEMORY_WC
, TRUE
},
88 { EFI_RESOURCE_ATTRIBUTE_WRITE_THROUGH_CACHEABLE
, EFI_MEMORY_WT
, TRUE
},
89 { EFI_RESOURCE_ATTRIBUTE_WRITE_BACK_CACHEABLE
, EFI_MEMORY_WB
, TRUE
},
90 { EFI_RESOURCE_ATTRIBUTE_READ_PROTECTABLE
, EFI_MEMORY_RP
, TRUE
},
91 { EFI_RESOURCE_ATTRIBUTE_WRITE_PROTECTABLE
, EFI_MEMORY_WP
, TRUE
},
92 { EFI_RESOURCE_ATTRIBUTE_EXECUTION_PROTECTABLE
, EFI_MEMORY_XP
, TRUE
},
93 { EFI_RESOURCE_ATTRIBUTE_PRESENT
, EFI_MEMORY_PRESENT
, FALSE
},
94 { EFI_RESOURCE_ATTRIBUTE_INITIALIZED
, EFI_MEMORY_INITIALIZED
, FALSE
},
95 { EFI_RESOURCE_ATTRIBUTE_TESTED
, EFI_MEMORY_TESTED
, FALSE
},
96 { EFI_RESOURCE_ATTRIBUTE_PERSISTABLE
, EFI_MEMORY_NV
, TRUE
},
101 /// Lookup table used to print GCD Memory Space Map
103 GLOBAL_REMOVE_IF_UNREFERENCED CONST CHAR8
*mGcdMemoryTypeNames
[] = {
104 "NonExist ", // EfiGcdMemoryTypeNonExistent
105 "Reserved ", // EfiGcdMemoryTypeReserved
106 "SystemMem", // EfiGcdMemoryTypeSystemMemory
107 "MMIO ", // EfiGcdMemoryTypeMemoryMappedIo
108 "PersistentMem",// EfiGcdMemoryTypePersistentMemory
109 "Unknown " // EfiGcdMemoryTypeMaximum
113 /// Lookup table used to print GCD I/O Space Map
115 GLOBAL_REMOVE_IF_UNREFERENCED CONST CHAR8
*mGcdIoTypeNames
[] = {
116 "NonExist", // EfiGcdIoTypeNonExistent
117 "Reserved", // EfiGcdIoTypeReserved
118 "I/O ", // EfiGcdIoTypeIo
119 "Unknown " // EfiGcdIoTypeMaximum
123 /// Lookup table used to print GCD Allocation Types
125 GLOBAL_REMOVE_IF_UNREFERENCED CONST CHAR8
*mGcdAllocationTypeNames
[] = {
126 "AnySearchBottomUp ", // EfiGcdAllocateAnySearchBottomUp
127 "MaxAddressSearchBottomUp ", // EfiGcdAllocateMaxAddressSearchBottomUp
128 "AtAddress ", // EfiGcdAllocateAddress
129 "AnySearchTopDown ", // EfiGcdAllocateAnySearchTopDown
130 "MaxAddressSearchTopDown ", // EfiGcdAllocateMaxAddressSearchTopDown
131 "Unknown " // EfiGcdMaxAllocateType
135 Dump the entire contents if the GCD Memory Space Map using DEBUG() macros when
136 PcdDebugPrintErrorLevel has the DEBUG_GCD bit set.
138 @param InitialMap TRUE if the initial GCD Memory Map is being dumped. Otherwise, FALSE.
143 CoreDumpGcdMemorySpaceMap (
149 UINTN NumberOfDescriptors
;
150 EFI_GCD_MEMORY_SPACE_DESCRIPTOR
*MemorySpaceMap
;
153 Status
= CoreGetMemorySpaceMap (&NumberOfDescriptors
, &MemorySpaceMap
);
154 ASSERT (Status
== EFI_SUCCESS
&& MemorySpaceMap
!= NULL
);
157 DEBUG ((DEBUG_GCD
, "GCD:Initial GCD Memory Space Map\n"));
159 DEBUG ((DEBUG_GCD
, "GCDMemType Range Capabilities Attributes \n"));
160 DEBUG ((DEBUG_GCD
, "========== ================================= ================ ================\n"));
161 for (Index
= 0; Index
< NumberOfDescriptors
; Index
++) {
162 DEBUG ((DEBUG_GCD
, "%a %016lx-%016lx %016lx %016lx%c\n",
163 mGcdMemoryTypeNames
[MIN (MemorySpaceMap
[Index
].GcdMemoryType
, EfiGcdMemoryTypeMaximum
)],
164 MemorySpaceMap
[Index
].BaseAddress
,
165 MemorySpaceMap
[Index
].BaseAddress
+ MemorySpaceMap
[Index
].Length
- 1,
166 MemorySpaceMap
[Index
].Capabilities
,
167 MemorySpaceMap
[Index
].Attributes
,
168 MemorySpaceMap
[Index
].ImageHandle
== NULL
? ' ' : '*'
171 DEBUG ((DEBUG_GCD
, "\n"));
172 FreePool (MemorySpaceMap
);
177 Dump the entire contents if the GCD I/O Space Map using DEBUG() macros when
178 PcdDebugPrintErrorLevel has the DEBUG_GCD bit set.
180 @param InitialMap TRUE if the initial GCD I/O Map is being dumped. Otherwise, FALSE.
185 CoreDumpGcdIoSpaceMap (
191 UINTN NumberOfDescriptors
;
192 EFI_GCD_IO_SPACE_DESCRIPTOR
*IoSpaceMap
;
195 Status
= CoreGetIoSpaceMap (&NumberOfDescriptors
, &IoSpaceMap
);
196 ASSERT (Status
== EFI_SUCCESS
&& IoSpaceMap
!= NULL
);
199 DEBUG ((DEBUG_GCD
, "GCD:Initial GCD I/O Space Map\n"));
202 DEBUG ((DEBUG_GCD
, "GCDIoType Range \n"));
203 DEBUG ((DEBUG_GCD
, "========== =================================\n"));
204 for (Index
= 0; Index
< NumberOfDescriptors
; Index
++) {
205 DEBUG ((DEBUG_GCD
, "%a %016lx-%016lx%c\n",
206 mGcdIoTypeNames
[MIN (IoSpaceMap
[Index
].GcdIoType
, EfiGcdIoTypeMaximum
)],
207 IoSpaceMap
[Index
].BaseAddress
,
208 IoSpaceMap
[Index
].BaseAddress
+ IoSpaceMap
[Index
].Length
- 1,
209 IoSpaceMap
[Index
].ImageHandle
== NULL
? ' ' : '*'
212 DEBUG ((DEBUG_GCD
, "\n"));
213 FreePool (IoSpaceMap
);
218 Validate resource descriptor HOB's attributes.
220 If Attributes includes some memory resource's settings, it should include
221 the corresponding capabilites also.
223 @param Attributes Resource descriptor HOB attributes.
227 CoreValidateResourceDescriptorHobAttributes (
231 ASSERT (((Attributes
& EFI_RESOURCE_ATTRIBUTE_READ_PROTECTED
) == 0) ||
232 ((Attributes
& EFI_RESOURCE_ATTRIBUTE_READ_PROTECTABLE
) != 0));
233 ASSERT (((Attributes
& EFI_RESOURCE_ATTRIBUTE_WRITE_PROTECTED
) == 0) ||
234 ((Attributes
& EFI_RESOURCE_ATTRIBUTE_WRITE_PROTECTABLE
) != 0));
235 ASSERT (((Attributes
& EFI_RESOURCE_ATTRIBUTE_EXECUTION_PROTECTED
) == 0) ||
236 ((Attributes
& EFI_RESOURCE_ATTRIBUTE_EXECUTION_PROTECTABLE
) != 0));
237 ASSERT (((Attributes
& EFI_RESOURCE_ATTRIBUTE_PERSISTENT
) == 0) ||
238 ((Attributes
& EFI_RESOURCE_ATTRIBUTE_PERSISTABLE
) != 0));
242 Acquire memory lock on mGcdMemorySpaceLock.
246 CoreAcquireGcdMemoryLock (
250 CoreAcquireLock (&mGcdMemorySpaceLock
);
256 Release memory lock on mGcdMemorySpaceLock.
260 CoreReleaseGcdMemoryLock (
264 CoreReleaseLock (&mGcdMemorySpaceLock
);
270 Acquire memory lock on mGcdIoSpaceLock.
274 CoreAcquireGcdIoLock (
278 CoreAcquireLock (&mGcdIoSpaceLock
);
283 Release memory lock on mGcdIoSpaceLock.
287 CoreReleaseGcdIoLock (
291 CoreReleaseLock (&mGcdIoSpaceLock
);
297 // GCD Initialization Worker Functions
300 Aligns a value to the specified boundary.
302 @param Value 64 bit value to align
303 @param Alignment Log base 2 of the boundary to align Value to
304 @param RoundUp TRUE if Value is to be rounded up to the nearest
305 aligned boundary. FALSE is Value is to be
306 rounded down to the nearest aligned boundary.
308 @return A 64 bit value is the aligned to the value nearest Value with an alignment by Alignment.
318 UINT64 AlignmentMask
;
320 AlignmentMask
= LShiftU64 (1, Alignment
) - 1;
322 Value
+= AlignmentMask
;
324 return Value
& (~AlignmentMask
);
329 Aligns address to the page boundary.
331 @param Value 64 bit address to align
333 @return A 64 bit value is the aligned to the value nearest Value with an alignment by Alignment.
341 return AlignValue (Value
, EFI_PAGE_SHIFT
, TRUE
);
346 Aligns length to the page boundary.
348 @param Value 64 bit length to align
350 @return A 64 bit value is the aligned to the value nearest Value with an alignment by Alignment.
358 return AlignValue (Value
, EFI_PAGE_SHIFT
, FALSE
);
362 // GCD Memory Space Worker Functions
366 Allocate pool for two entries.
368 @param TopEntry An entry of GCD map
369 @param BottomEntry An entry of GCD map
371 @retval EFI_OUT_OF_RESOURCES No enough buffer to be allocated.
372 @retval EFI_SUCCESS Both entries successfully allocated.
376 CoreAllocateGcdMapEntry (
377 IN OUT EFI_GCD_MAP_ENTRY
**TopEntry
,
378 IN OUT EFI_GCD_MAP_ENTRY
**BottomEntry
381 *TopEntry
= AllocateZeroPool (sizeof (EFI_GCD_MAP_ENTRY
));
382 if (*TopEntry
== NULL
) {
383 return EFI_OUT_OF_RESOURCES
;
386 *BottomEntry
= AllocateZeroPool (sizeof (EFI_GCD_MAP_ENTRY
));
387 if (*BottomEntry
== NULL
) {
388 CoreFreePool (*TopEntry
);
389 return EFI_OUT_OF_RESOURCES
;
397 Internal function. Inserts a new descriptor into a sorted list
399 @param Link The linked list to insert the range BaseAddress
401 @param Entry A pointer to the entry that is inserted
402 @param BaseAddress The base address of the new range
403 @param Length The length of the new range in bytes
404 @param TopEntry Top pad entry to insert if needed.
405 @param BottomEntry Bottom pad entry to insert if needed.
407 @retval EFI_SUCCESS The new range was inserted into the linked list
411 CoreInsertGcdMapEntry (
413 IN EFI_GCD_MAP_ENTRY
*Entry
,
414 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
416 IN EFI_GCD_MAP_ENTRY
*TopEntry
,
417 IN EFI_GCD_MAP_ENTRY
*BottomEntry
420 ASSERT (Length
!= 0);
422 if (BaseAddress
> Entry
->BaseAddress
) {
423 ASSERT (BottomEntry
->Signature
== 0);
425 CopyMem (BottomEntry
, Entry
, sizeof (EFI_GCD_MAP_ENTRY
));
426 Entry
->BaseAddress
= BaseAddress
;
427 BottomEntry
->EndAddress
= BaseAddress
- 1;
428 InsertTailList (Link
, &BottomEntry
->Link
);
431 if ((BaseAddress
+ Length
- 1) < Entry
->EndAddress
) {
432 ASSERT (TopEntry
->Signature
== 0);
434 CopyMem (TopEntry
, Entry
, sizeof (EFI_GCD_MAP_ENTRY
));
435 TopEntry
->BaseAddress
= BaseAddress
+ Length
;
436 Entry
->EndAddress
= BaseAddress
+ Length
- 1;
437 InsertHeadList (Link
, &TopEntry
->Link
);
445 Merge the Gcd region specified by Link and its adjacent entry.
447 @param Link Specify the entry to be merged (with its
449 @param Forward Direction (forward or backward).
452 @retval EFI_SUCCESS Successfully returned.
453 @retval EFI_UNSUPPORTED These adjacent regions could not merge.
457 CoreMergeGcdMapEntry (
463 LIST_ENTRY
*AdjacentLink
;
464 EFI_GCD_MAP_ENTRY
*Entry
;
465 EFI_GCD_MAP_ENTRY
*AdjacentEntry
;
468 // Get adjacent entry
471 AdjacentLink
= Link
->ForwardLink
;
473 AdjacentLink
= Link
->BackLink
;
477 // If AdjacentLink is the head of the list, then no merge can be performed
479 if (AdjacentLink
== Map
) {
483 Entry
= CR (Link
, EFI_GCD_MAP_ENTRY
, Link
, EFI_GCD_MAP_SIGNATURE
);
484 AdjacentEntry
= CR (AdjacentLink
, EFI_GCD_MAP_ENTRY
, Link
, EFI_GCD_MAP_SIGNATURE
);
486 if (Entry
->Capabilities
!= AdjacentEntry
->Capabilities
) {
487 return EFI_UNSUPPORTED
;
489 if (Entry
->Attributes
!= AdjacentEntry
->Attributes
) {
490 return EFI_UNSUPPORTED
;
492 if (Entry
->GcdMemoryType
!= AdjacentEntry
->GcdMemoryType
) {
493 return EFI_UNSUPPORTED
;
495 if (Entry
->GcdIoType
!= AdjacentEntry
->GcdIoType
) {
496 return EFI_UNSUPPORTED
;
498 if (Entry
->ImageHandle
!= AdjacentEntry
->ImageHandle
) {
499 return EFI_UNSUPPORTED
;
501 if (Entry
->DeviceHandle
!= AdjacentEntry
->DeviceHandle
) {
502 return EFI_UNSUPPORTED
;
506 Entry
->EndAddress
= AdjacentEntry
->EndAddress
;
508 Entry
->BaseAddress
= AdjacentEntry
->BaseAddress
;
510 RemoveEntryList (AdjacentLink
);
511 CoreFreePool (AdjacentEntry
);
518 Merge adjacent entries on total chain.
520 @param TopEntry Top entry of GCD map.
521 @param BottomEntry Bottom entry of GCD map.
522 @param StartLink Start link of the list for this loop.
523 @param EndLink End link of the list for this loop.
526 @retval EFI_SUCCESS GCD map successfully cleaned up.
530 CoreCleanupGcdMapEntry (
531 IN EFI_GCD_MAP_ENTRY
*TopEntry
,
532 IN EFI_GCD_MAP_ENTRY
*BottomEntry
,
533 IN LIST_ENTRY
*StartLink
,
534 IN LIST_ENTRY
*EndLink
,
540 if (TopEntry
->Signature
== 0) {
541 CoreFreePool (TopEntry
);
543 if (BottomEntry
->Signature
== 0) {
544 CoreFreePool (BottomEntry
);
548 while (Link
!= EndLink
->ForwardLink
) {
549 CoreMergeGcdMapEntry (Link
, FALSE
, Map
);
550 Link
= Link
->ForwardLink
;
552 CoreMergeGcdMapEntry (EndLink
, TRUE
, Map
);
559 Search a segment of memory space in GCD map. The result is a range of GCD entry list.
561 @param BaseAddress The start address of the segment.
562 @param Length The length of the segment.
563 @param StartLink The first GCD entry involves this segment of
565 @param EndLink The first GCD entry involves this segment of
567 @param Map Points to the start entry to search.
569 @retval EFI_SUCCESS Successfully found the entry.
570 @retval EFI_NOT_FOUND Not found.
574 CoreSearchGcdMapEntry (
575 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
577 OUT LIST_ENTRY
**StartLink
,
578 OUT LIST_ENTRY
**EndLink
,
583 EFI_GCD_MAP_ENTRY
*Entry
;
585 ASSERT (Length
!= 0);
590 Link
= Map
->ForwardLink
;
591 while (Link
!= Map
) {
592 Entry
= CR (Link
, EFI_GCD_MAP_ENTRY
, Link
, EFI_GCD_MAP_SIGNATURE
);
593 if (BaseAddress
>= Entry
->BaseAddress
&& BaseAddress
<= Entry
->EndAddress
) {
596 if (*StartLink
!= NULL
) {
597 if ((BaseAddress
+ Length
- 1) >= Entry
->BaseAddress
&&
598 (BaseAddress
+ Length
- 1) <= Entry
->EndAddress
) {
603 Link
= Link
->ForwardLink
;
606 return EFI_NOT_FOUND
;
611 Count the amount of GCD map entries.
613 @param Map Points to the start entry to do the count loop.
619 CoreCountGcdMapEntry (
627 Link
= Map
->ForwardLink
;
628 while (Link
!= Map
) {
630 Link
= Link
->ForwardLink
;
639 Return the memory attribute specified by Attributes
641 @param Attributes A num with some attribute bits on.
643 @return The enum value of memory attribute.
647 ConverToCpuArchAttributes (
651 if ( (Attributes
& EFI_MEMORY_UC
) == EFI_MEMORY_UC
) {
652 return EFI_MEMORY_UC
;
655 if ( (Attributes
& EFI_MEMORY_WC
) == EFI_MEMORY_WC
) {
656 return EFI_MEMORY_WC
;
659 if ( (Attributes
& EFI_MEMORY_WT
) == EFI_MEMORY_WT
) {
660 return EFI_MEMORY_WT
;
663 if ( (Attributes
& EFI_MEMORY_WB
) == EFI_MEMORY_WB
) {
664 return EFI_MEMORY_WB
;
667 if ( (Attributes
& EFI_MEMORY_WP
) == EFI_MEMORY_WP
) {
668 return EFI_MEMORY_WP
;
671 return INVALID_CPU_ARCH_ATTRIBUTES
;
677 Do operation on a segment of memory space specified (add, free, remove, change attribute ...).
679 @param Operation The type of the operation
680 @param GcdMemoryType Additional information for the operation
681 @param GcdIoType Additional information for the operation
682 @param BaseAddress Start address of the segment
683 @param Length length of the segment
684 @param Capabilities The alterable attributes of a newly added entry
685 @param Attributes The attributes needs to be set
687 @retval EFI_INVALID_PARAMETER Length is 0 or address (length) not aligned when
689 @retval EFI_SUCCESS Action successfully done.
690 @retval EFI_UNSUPPORTED Could not find the proper descriptor on this
691 segment or set an upsupported attribute.
692 @retval EFI_ACCESS_DENIED Operate on an space non-exist or is used for an
694 @retval EFI_NOT_FOUND Free a non-using space or remove a non-exist
696 @retval EFI_OUT_OF_RESOURCES No buffer could be allocated.
697 @retval EFI_NOT_AVAILABLE_YET The attributes cannot be set because CPU architectural protocol
698 is not available yet.
703 IN EFI_GCD_MEMORY_TYPE GcdMemoryType
,
704 IN EFI_GCD_IO_TYPE GcdIoType
,
705 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
707 IN UINT64 Capabilities
,
714 EFI_GCD_MAP_ENTRY
*Entry
;
715 EFI_GCD_MAP_ENTRY
*TopEntry
;
716 EFI_GCD_MAP_ENTRY
*BottomEntry
;
717 LIST_ENTRY
*StartLink
;
719 UINT64 CpuArchAttributes
;
722 DEBUG ((DEBUG_GCD
, " Status = %r\n", EFI_INVALID_PARAMETER
));
723 return EFI_INVALID_PARAMETER
;
727 if ((Operation
& GCD_MEMORY_SPACE_OPERATION
) != 0) {
728 CoreAcquireGcdMemoryLock ();
729 Map
= &mGcdMemorySpaceMap
;
730 } else if ((Operation
& GCD_IO_SPACE_OPERATION
) != 0) {
731 CoreAcquireGcdIoLock ();
732 Map
= &mGcdIoSpaceMap
;
738 // Search for the list of descriptors that cover the range BaseAddress to BaseAddress+Length
740 Status
= CoreSearchGcdMapEntry (BaseAddress
, Length
, &StartLink
, &EndLink
, Map
);
741 if (EFI_ERROR (Status
)) {
742 Status
= EFI_UNSUPPORTED
;
746 ASSERT (StartLink
!= NULL
&& EndLink
!= NULL
);
749 // Verify that the list of descriptors are unallocated non-existent memory.
752 while (Link
!= EndLink
->ForwardLink
) {
753 Entry
= CR (Link
, EFI_GCD_MAP_ENTRY
, Link
, EFI_GCD_MAP_SIGNATURE
);
758 case GCD_ADD_MEMORY_OPERATION
:
759 if (Entry
->GcdMemoryType
!= EfiGcdMemoryTypeNonExistent
||
760 Entry
->ImageHandle
!= NULL
) {
761 Status
= EFI_ACCESS_DENIED
;
765 case GCD_ADD_IO_OPERATION
:
766 if (Entry
->GcdIoType
!= EfiGcdIoTypeNonExistent
||
767 Entry
->ImageHandle
!= NULL
) {
768 Status
= EFI_ACCESS_DENIED
;
775 case GCD_FREE_MEMORY_OPERATION
:
776 case GCD_FREE_IO_OPERATION
:
777 if (Entry
->ImageHandle
== NULL
) {
778 Status
= EFI_NOT_FOUND
;
785 case GCD_REMOVE_MEMORY_OPERATION
:
786 if (Entry
->GcdMemoryType
== EfiGcdMemoryTypeNonExistent
) {
787 Status
= EFI_NOT_FOUND
;
790 if (Entry
->ImageHandle
!= NULL
) {
791 Status
= EFI_ACCESS_DENIED
;
795 case GCD_REMOVE_IO_OPERATION
:
796 if (Entry
->GcdIoType
== EfiGcdIoTypeNonExistent
) {
797 Status
= EFI_NOT_FOUND
;
800 if (Entry
->ImageHandle
!= NULL
) {
801 Status
= EFI_ACCESS_DENIED
;
806 // Set attributes operation
808 case GCD_SET_ATTRIBUTES_MEMORY_OPERATION
:
809 if ((Attributes
& EFI_MEMORY_RUNTIME
) != 0) {
810 if ((BaseAddress
& EFI_PAGE_MASK
) != 0 || (Length
& EFI_PAGE_MASK
) != 0) {
811 Status
= EFI_INVALID_PARAMETER
;
815 if ((Entry
->Capabilities
& Attributes
) != Attributes
) {
816 Status
= EFI_UNSUPPORTED
;
821 // Set capabilities operation
823 case GCD_SET_CAPABILITIES_MEMORY_OPERATION
:
824 if ((BaseAddress
& EFI_PAGE_MASK
) != 0 || (Length
& EFI_PAGE_MASK
) != 0) {
825 Status
= EFI_INVALID_PARAMETER
;
830 // Current attributes must still be supported with new capabilities
832 if ((Capabilities
& Entry
->Attributes
) != Entry
->Attributes
) {
833 Status
= EFI_UNSUPPORTED
;
838 Link
= Link
->ForwardLink
;
842 // Allocate work space to perform this operation
844 Status
= CoreAllocateGcdMapEntry (&TopEntry
, &BottomEntry
);
845 if (EFI_ERROR (Status
)) {
846 Status
= EFI_OUT_OF_RESOURCES
;
849 ASSERT (TopEntry
!= NULL
&& BottomEntry
!= NULL
);
851 if (Operation
== GCD_SET_ATTRIBUTES_MEMORY_OPERATION
) {
853 // Call CPU Arch Protocol to attempt to set attributes on the range
855 CpuArchAttributes
= ConverToCpuArchAttributes (Attributes
);
856 if (CpuArchAttributes
!= INVALID_CPU_ARCH_ATTRIBUTES
) {
858 Status
= EFI_NOT_AVAILABLE_YET
;
860 Status
= gCpu
->SetMemoryAttributes (
867 if (EFI_ERROR (Status
)) {
868 CoreFreePool (TopEntry
);
869 CoreFreePool (BottomEntry
);
876 // Convert/Insert the list of descriptors from StartLink to EndLink
879 while (Link
!= EndLink
->ForwardLink
) {
880 Entry
= CR (Link
, EFI_GCD_MAP_ENTRY
, Link
, EFI_GCD_MAP_SIGNATURE
);
881 CoreInsertGcdMapEntry (Link
, Entry
, BaseAddress
, Length
, TopEntry
, BottomEntry
);
886 case GCD_ADD_MEMORY_OPERATION
:
887 Entry
->GcdMemoryType
= GcdMemoryType
;
888 if (GcdMemoryType
== EfiGcdMemoryTypeMemoryMappedIo
) {
889 Entry
->Capabilities
= Capabilities
| EFI_MEMORY_RUNTIME
| EFI_MEMORY_PORT_IO
;
891 Entry
->Capabilities
= Capabilities
| EFI_MEMORY_RUNTIME
;
894 case GCD_ADD_IO_OPERATION
:
895 Entry
->GcdIoType
= GcdIoType
;
900 case GCD_FREE_MEMORY_OPERATION
:
901 case GCD_FREE_IO_OPERATION
:
902 Entry
->ImageHandle
= NULL
;
903 Entry
->DeviceHandle
= NULL
;
908 case GCD_REMOVE_MEMORY_OPERATION
:
909 Entry
->GcdMemoryType
= EfiGcdMemoryTypeNonExistent
;
910 Entry
->Capabilities
= 0;
912 case GCD_REMOVE_IO_OPERATION
:
913 Entry
->GcdIoType
= EfiGcdIoTypeNonExistent
;
916 // Set attributes operation
918 case GCD_SET_ATTRIBUTES_MEMORY_OPERATION
:
919 Entry
->Attributes
= Attributes
;
922 // Set capabilities operation
924 case GCD_SET_CAPABILITIES_MEMORY_OPERATION
:
925 Entry
->Capabilities
= Capabilities
;
928 Link
= Link
->ForwardLink
;
934 Status
= CoreCleanupGcdMapEntry (TopEntry
, BottomEntry
, StartLink
, EndLink
, Map
);
937 DEBUG ((DEBUG_GCD
, " Status = %r\n", Status
));
939 if ((Operation
& GCD_MEMORY_SPACE_OPERATION
) != 0) {
940 CoreReleaseGcdMemoryLock ();
941 CoreDumpGcdMemorySpaceMap (FALSE
);
943 if ((Operation
& GCD_IO_SPACE_OPERATION
) != 0) {
944 CoreReleaseGcdIoLock ();
945 CoreDumpGcdIoSpaceMap (FALSE
);
953 Check whether an entry could be used to allocate space.
955 @param Operation Allocate memory or IO
956 @param Entry The entry to be tested
957 @param GcdMemoryType The desired memory type
958 @param GcdIoType The desired IO type
960 @retval EFI_NOT_FOUND The memory type does not match or there's an
961 image handle on the entry.
962 @retval EFI_UNSUPPORTED The operation unsupported.
963 @retval EFI_SUCCESS It's ok for this entry to be used to allocate
968 CoreAllocateSpaceCheckEntry (
970 IN EFI_GCD_MAP_ENTRY
*Entry
,
971 IN EFI_GCD_MEMORY_TYPE GcdMemoryType
,
972 IN EFI_GCD_IO_TYPE GcdIoType
975 if (Entry
->ImageHandle
!= NULL
) {
976 return EFI_NOT_FOUND
;
979 case GCD_ALLOCATE_MEMORY_OPERATION
:
980 if (Entry
->GcdMemoryType
!= GcdMemoryType
) {
981 return EFI_NOT_FOUND
;
984 case GCD_ALLOCATE_IO_OPERATION
:
985 if (Entry
->GcdIoType
!= GcdIoType
) {
986 return EFI_NOT_FOUND
;
990 return EFI_UNSUPPORTED
;
997 Allocate space on specified address and length.
999 @param Operation The type of operation (memory or IO)
1000 @param GcdAllocateType The type of allocate operation
1001 @param GcdMemoryType The desired memory type
1002 @param GcdIoType The desired IO type
1003 @param Alignment Align with 2^Alignment
1004 @param Length Length to allocate
1005 @param BaseAddress Base address to allocate
1006 @param ImageHandle The image handle consume the allocated space.
1007 @param DeviceHandle The device handle consume the allocated space.
1009 @retval EFI_INVALID_PARAMETER Invalid parameter.
1010 @retval EFI_NOT_FOUND No descriptor for the desired space exists.
1011 @retval EFI_SUCCESS Space successfully allocated.
1017 IN EFI_GCD_ALLOCATE_TYPE GcdAllocateType
,
1018 IN EFI_GCD_MEMORY_TYPE GcdMemoryType
,
1019 IN EFI_GCD_IO_TYPE GcdIoType
,
1022 IN OUT EFI_PHYSICAL_ADDRESS
*BaseAddress
,
1023 IN EFI_HANDLE ImageHandle
,
1024 IN EFI_HANDLE DeviceHandle OPTIONAL
1028 EFI_PHYSICAL_ADDRESS AlignmentMask
;
1029 EFI_PHYSICAL_ADDRESS MaxAddress
;
1032 LIST_ENTRY
*SubLink
;
1033 EFI_GCD_MAP_ENTRY
*Entry
;
1034 EFI_GCD_MAP_ENTRY
*TopEntry
;
1035 EFI_GCD_MAP_ENTRY
*BottomEntry
;
1036 LIST_ENTRY
*StartLink
;
1037 LIST_ENTRY
*EndLink
;
1041 // Make sure parameters are valid
1043 if ((UINT32
)GcdAllocateType
>= EfiGcdMaxAllocateType
) {
1044 DEBUG ((DEBUG_GCD
, " Status = %r\n", EFI_INVALID_PARAMETER
));
1045 return EFI_INVALID_PARAMETER
;
1047 if ((UINT32
)GcdMemoryType
>= EfiGcdMemoryTypeMaximum
) {
1048 DEBUG ((DEBUG_GCD
, " Status = %r\n", EFI_INVALID_PARAMETER
));
1049 return EFI_INVALID_PARAMETER
;
1051 if ((UINT32
)GcdIoType
>= EfiGcdIoTypeMaximum
) {
1052 DEBUG ((DEBUG_GCD
, " Status = %r\n", EFI_INVALID_PARAMETER
));
1053 return EFI_INVALID_PARAMETER
;
1055 if (BaseAddress
== NULL
) {
1056 DEBUG ((DEBUG_GCD
, " Status = %r\n", EFI_INVALID_PARAMETER
));
1057 return EFI_INVALID_PARAMETER
;
1059 if (ImageHandle
== NULL
) {
1060 DEBUG ((DEBUG_GCD
, " Status = %r\n", EFI_INVALID_PARAMETER
));
1061 return EFI_INVALID_PARAMETER
;
1063 if (Alignment
>= 64) {
1064 DEBUG ((DEBUG_GCD
, " Status = %r\n", EFI_NOT_FOUND
));
1065 return EFI_NOT_FOUND
;
1068 DEBUG ((DEBUG_GCD
, " Status = %r\n", EFI_INVALID_PARAMETER
));
1069 return EFI_INVALID_PARAMETER
;
1073 if ((Operation
& GCD_MEMORY_SPACE_OPERATION
) != 0) {
1074 CoreAcquireGcdMemoryLock ();
1075 Map
= &mGcdMemorySpaceMap
;
1076 } else if ((Operation
& GCD_IO_SPACE_OPERATION
) != 0) {
1077 CoreAcquireGcdIoLock ();
1078 Map
= &mGcdIoSpaceMap
;
1087 // Compute alignment bit mask
1089 AlignmentMask
= LShiftU64 (1, Alignment
) - 1;
1091 if (GcdAllocateType
== EfiGcdAllocateAddress
) {
1093 // Verify that the BaseAddress passed in is aligned correctly
1095 if ((*BaseAddress
& AlignmentMask
) != 0) {
1096 Status
= EFI_NOT_FOUND
;
1101 // Search for the list of descriptors that cover the range BaseAddress to BaseAddress+Length
1103 Status
= CoreSearchGcdMapEntry (*BaseAddress
, Length
, &StartLink
, &EndLink
, Map
);
1104 if (EFI_ERROR (Status
)) {
1105 Status
= EFI_NOT_FOUND
;
1108 ASSERT (StartLink
!= NULL
&& EndLink
!= NULL
);
1111 // Verify that the list of descriptors are unallocated memory matching GcdMemoryType.
1114 while (Link
!= EndLink
->ForwardLink
) {
1115 Entry
= CR (Link
, EFI_GCD_MAP_ENTRY
, Link
, EFI_GCD_MAP_SIGNATURE
);
1116 Link
= Link
->ForwardLink
;
1117 Status
= CoreAllocateSpaceCheckEntry (Operation
, Entry
, GcdMemoryType
, GcdIoType
);
1118 if (EFI_ERROR (Status
)) {
1125 Entry
= CR (Map
->BackLink
, EFI_GCD_MAP_ENTRY
, Link
, EFI_GCD_MAP_SIGNATURE
);
1128 // Compute the maximum address to use in the search algorithm
1130 if (GcdAllocateType
== EfiGcdAllocateMaxAddressSearchBottomUp
||
1131 GcdAllocateType
== EfiGcdAllocateMaxAddressSearchTopDown
) {
1132 MaxAddress
= *BaseAddress
;
1134 MaxAddress
= Entry
->EndAddress
;
1138 // Verify that the list of descriptors are unallocated memory matching GcdMemoryType.
1140 if (GcdAllocateType
== EfiGcdAllocateMaxAddressSearchTopDown
||
1141 GcdAllocateType
== EfiGcdAllocateAnySearchTopDown
) {
1142 Link
= Map
->BackLink
;
1144 Link
= Map
->ForwardLink
;
1146 while (Link
!= Map
) {
1147 Entry
= CR (Link
, EFI_GCD_MAP_ENTRY
, Link
, EFI_GCD_MAP_SIGNATURE
);
1149 if (GcdAllocateType
== EfiGcdAllocateMaxAddressSearchTopDown
||
1150 GcdAllocateType
== EfiGcdAllocateAnySearchTopDown
) {
1151 Link
= Link
->BackLink
;
1153 Link
= Link
->ForwardLink
;
1156 Status
= CoreAllocateSpaceCheckEntry (Operation
, Entry
, GcdMemoryType
, GcdIoType
);
1157 if (EFI_ERROR (Status
)) {
1161 if (GcdAllocateType
== EfiGcdAllocateMaxAddressSearchTopDown
||
1162 GcdAllocateType
== EfiGcdAllocateAnySearchTopDown
) {
1163 if ((Entry
->BaseAddress
+ Length
) > MaxAddress
) {
1166 if (Length
> (Entry
->EndAddress
+ 1)) {
1167 Status
= EFI_NOT_FOUND
;
1170 if (Entry
->EndAddress
> MaxAddress
) {
1171 *BaseAddress
= MaxAddress
;
1173 *BaseAddress
= Entry
->EndAddress
;
1175 *BaseAddress
= (*BaseAddress
+ 1 - Length
) & (~AlignmentMask
);
1177 *BaseAddress
= (Entry
->BaseAddress
+ AlignmentMask
) & (~AlignmentMask
);
1178 if ((*BaseAddress
+ Length
- 1) > MaxAddress
) {
1179 Status
= EFI_NOT_FOUND
;
1185 // Search for the list of descriptors that cover the range BaseAddress to BaseAddress+Length
1187 Status
= CoreSearchGcdMapEntry (*BaseAddress
, Length
, &StartLink
, &EndLink
, Map
);
1188 if (EFI_ERROR (Status
)) {
1189 Status
= EFI_NOT_FOUND
;
1192 ASSERT (StartLink
!= NULL
&& EndLink
!= NULL
);
1196 // Verify that the list of descriptors are unallocated memory matching GcdMemoryType.
1199 SubLink
= StartLink
;
1200 while (SubLink
!= EndLink
->ForwardLink
) {
1201 Entry
= CR (SubLink
, EFI_GCD_MAP_ENTRY
, Link
, EFI_GCD_MAP_SIGNATURE
);
1202 Status
= CoreAllocateSpaceCheckEntry (Operation
, Entry
, GcdMemoryType
, GcdIoType
);
1203 if (EFI_ERROR (Status
)) {
1208 SubLink
= SubLink
->ForwardLink
;
1216 Status
= EFI_NOT_FOUND
;
1221 // Allocate work space to perform this operation
1223 Status
= CoreAllocateGcdMapEntry (&TopEntry
, &BottomEntry
);
1224 if (EFI_ERROR (Status
)) {
1225 Status
= EFI_OUT_OF_RESOURCES
;
1228 ASSERT (TopEntry
!= NULL
&& BottomEntry
!= NULL
);
1231 // Convert/Insert the list of descriptors from StartLink to EndLink
1234 while (Link
!= EndLink
->ForwardLink
) {
1235 Entry
= CR (Link
, EFI_GCD_MAP_ENTRY
, Link
, EFI_GCD_MAP_SIGNATURE
);
1236 CoreInsertGcdMapEntry (Link
, Entry
, *BaseAddress
, Length
, TopEntry
, BottomEntry
);
1237 Entry
->ImageHandle
= ImageHandle
;
1238 Entry
->DeviceHandle
= DeviceHandle
;
1239 Link
= Link
->ForwardLink
;
1245 Status
= CoreCleanupGcdMapEntry (TopEntry
, BottomEntry
, StartLink
, EndLink
, Map
);
1248 DEBUG ((DEBUG_GCD
, " Status = %r", Status
));
1249 if (!EFI_ERROR (Status
)) {
1250 DEBUG ((DEBUG_GCD
, " (BaseAddress = %016lx)", *BaseAddress
));
1252 DEBUG ((DEBUG_GCD
, "\n"));
1254 if ((Operation
& GCD_MEMORY_SPACE_OPERATION
) != 0) {
1255 CoreReleaseGcdMemoryLock ();
1256 CoreDumpGcdMemorySpaceMap (FALSE
);
1258 if ((Operation
& GCD_IO_SPACE_OPERATION
) !=0) {
1259 CoreReleaseGcdIoLock ();
1260 CoreDumpGcdIoSpaceMap (FALSE
);
1268 Add a segment of memory to GCD map.
1270 @param GcdMemoryType Memory type of the segment.
1271 @param BaseAddress Base address of the segment.
1272 @param Length Length of the segment.
1273 @param Capabilities alterable attributes of the segment.
1275 @retval EFI_INVALID_PARAMETER Invalid parameters.
1276 @retval EFI_SUCCESS Successfully add a segment of memory space.
1280 CoreInternalAddMemorySpace (
1281 IN EFI_GCD_MEMORY_TYPE GcdMemoryType
,
1282 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
1284 IN UINT64 Capabilities
1287 DEBUG ((DEBUG_GCD
, "GCD:AddMemorySpace(Base=%016lx,Length=%016lx)\n", BaseAddress
, Length
));
1288 DEBUG ((DEBUG_GCD
, " GcdMemoryType = %a\n", mGcdMemoryTypeNames
[MIN (GcdMemoryType
, EfiGcdMemoryTypeMaximum
)]));
1289 DEBUG ((DEBUG_GCD
, " Capabilities = %016lx\n", Capabilities
));
1292 // Make sure parameters are valid
1294 if (GcdMemoryType
<= EfiGcdMemoryTypeNonExistent
|| GcdMemoryType
>= EfiGcdMemoryTypeMaximum
) {
1295 return EFI_INVALID_PARAMETER
;
1298 return CoreConvertSpace (GCD_ADD_MEMORY_OPERATION
, GcdMemoryType
, (EFI_GCD_IO_TYPE
) 0, BaseAddress
, Length
, Capabilities
, 0);
1302 // GCD Core Services
1306 Allocates nonexistent memory, reserved memory, system memory, or memorymapped
1307 I/O resources from the global coherency domain of the processor.
1309 @param GcdAllocateType The type of allocate operation
1310 @param GcdMemoryType The desired memory type
1311 @param Alignment Align with 2^Alignment
1312 @param Length Length to allocate
1313 @param BaseAddress Base address to allocate
1314 @param ImageHandle The image handle consume the allocated space.
1315 @param DeviceHandle The device handle consume the allocated space.
1317 @retval EFI_INVALID_PARAMETER Invalid parameter.
1318 @retval EFI_NOT_FOUND No descriptor contains the desired space.
1319 @retval EFI_SUCCESS Memory space successfully allocated.
1324 CoreAllocateMemorySpace (
1325 IN EFI_GCD_ALLOCATE_TYPE GcdAllocateType
,
1326 IN EFI_GCD_MEMORY_TYPE GcdMemoryType
,
1329 IN OUT EFI_PHYSICAL_ADDRESS
*BaseAddress
,
1330 IN EFI_HANDLE ImageHandle
,
1331 IN EFI_HANDLE DeviceHandle OPTIONAL
1334 DEBUG ((DEBUG_GCD
, "GCD:AllocateMemorySpace(Base=%016lx,Length=%016lx)\n", *BaseAddress
, Length
));
1335 DEBUG ((DEBUG_GCD
, " GcdAllocateType = %a\n", mGcdAllocationTypeNames
[MIN (GcdAllocateType
, EfiGcdMaxAllocateType
)]));
1336 DEBUG ((DEBUG_GCD
, " GcdMemoryType = %a\n", mGcdMemoryTypeNames
[MIN (GcdMemoryType
, EfiGcdMemoryTypeMaximum
)]));
1337 DEBUG ((DEBUG_GCD
, " Alignment = %016lx\n", LShiftU64 (1, Alignment
)));
1338 DEBUG ((DEBUG_GCD
, " ImageHandle = %p\n", ImageHandle
));
1339 DEBUG ((DEBUG_GCD
, " DeviceHandle = %p\n", DeviceHandle
));
1341 return CoreAllocateSpace (
1342 GCD_ALLOCATE_MEMORY_OPERATION
,
1345 (EFI_GCD_IO_TYPE
) 0,
1356 Adds reserved memory, system memory, or memory-mapped I/O resources to the
1357 global coherency domain of the processor.
1359 @param GcdMemoryType Memory type of the memory space.
1360 @param BaseAddress Base address of the memory space.
1361 @param Length Length of the memory space.
1362 @param Capabilities alterable attributes of the memory space.
1364 @retval EFI_SUCCESS Merged this memory space into GCD map.
1369 CoreAddMemorySpace (
1370 IN EFI_GCD_MEMORY_TYPE GcdMemoryType
,
1371 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
1373 IN UINT64 Capabilities
1377 EFI_PHYSICAL_ADDRESS PageBaseAddress
;
1380 Status
= CoreInternalAddMemorySpace (GcdMemoryType
, BaseAddress
, Length
, Capabilities
);
1382 if (!EFI_ERROR (Status
) && GcdMemoryType
== EfiGcdMemoryTypeSystemMemory
) {
1384 PageBaseAddress
= PageAlignLength (BaseAddress
);
1385 PageLength
= PageAlignLength (BaseAddress
+ Length
- PageBaseAddress
);
1387 Status
= CoreAllocateMemorySpace (
1388 EfiGcdAllocateAddress
,
1393 gDxeCoreImageHandle
,
1397 if (!EFI_ERROR (Status
)) {
1398 CoreAddMemoryDescriptor (
1399 EfiConventionalMemory
,
1401 RShiftU64 (PageLength
, EFI_PAGE_SHIFT
),
1405 for (; PageLength
!= 0; PageLength
-= EFI_PAGE_SIZE
, PageBaseAddress
+= EFI_PAGE_SIZE
) {
1406 Status
= CoreAllocateMemorySpace (
1407 EfiGcdAllocateAddress
,
1412 gDxeCoreImageHandle
,
1416 if (!EFI_ERROR (Status
)) {
1417 CoreAddMemoryDescriptor (
1418 EfiConventionalMemory
,
1432 Frees nonexistent memory, reserved memory, system memory, or memory-mapped
1433 I/O resources from the global coherency domain of the processor.
1435 @param BaseAddress Base address of the memory space.
1436 @param Length Length of the memory space.
1438 @retval EFI_SUCCESS Space successfully freed.
1443 CoreFreeMemorySpace (
1444 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
1448 DEBUG ((DEBUG_GCD
, "GCD:FreeMemorySpace(Base=%016lx,Length=%016lx)\n", BaseAddress
, Length
));
1450 return CoreConvertSpace (GCD_FREE_MEMORY_OPERATION
, (EFI_GCD_MEMORY_TYPE
) 0, (EFI_GCD_IO_TYPE
) 0, BaseAddress
, Length
, 0, 0);
1455 Removes reserved memory, system memory, or memory-mapped I/O resources from
1456 the global coherency domain of the processor.
1458 @param BaseAddress Base address of the memory space.
1459 @param Length Length of the memory space.
1461 @retval EFI_SUCCESS Successfully remove a segment of memory space.
1466 CoreRemoveMemorySpace (
1467 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
1471 DEBUG ((DEBUG_GCD
, "GCD:RemoveMemorySpace(Base=%016lx,Length=%016lx)\n", BaseAddress
, Length
));
1473 return CoreConvertSpace (GCD_REMOVE_MEMORY_OPERATION
, (EFI_GCD_MEMORY_TYPE
) 0, (EFI_GCD_IO_TYPE
) 0, BaseAddress
, Length
, 0, 0);
1478 Build a memory descriptor according to an entry.
1480 @param Descriptor The descriptor to be built
1481 @param Entry According to this entry
1485 BuildMemoryDescriptor (
1486 IN OUT EFI_GCD_MEMORY_SPACE_DESCRIPTOR
*Descriptor
,
1487 IN EFI_GCD_MAP_ENTRY
*Entry
1490 Descriptor
->BaseAddress
= Entry
->BaseAddress
;
1491 Descriptor
->Length
= Entry
->EndAddress
- Entry
->BaseAddress
+ 1;
1492 Descriptor
->Capabilities
= Entry
->Capabilities
;
1493 Descriptor
->Attributes
= Entry
->Attributes
;
1494 Descriptor
->GcdMemoryType
= Entry
->GcdMemoryType
;
1495 Descriptor
->ImageHandle
= Entry
->ImageHandle
;
1496 Descriptor
->DeviceHandle
= Entry
->DeviceHandle
;
1501 Retrieves the descriptor for a memory region containing a specified address.
1503 @param BaseAddress Specified start address
1504 @param Descriptor Specified length
1506 @retval EFI_INVALID_PARAMETER Invalid parameter
1507 @retval EFI_SUCCESS Successfully get memory space descriptor.
1512 CoreGetMemorySpaceDescriptor (
1513 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
1514 OUT EFI_GCD_MEMORY_SPACE_DESCRIPTOR
*Descriptor
1518 LIST_ENTRY
*StartLink
;
1519 LIST_ENTRY
*EndLink
;
1520 EFI_GCD_MAP_ENTRY
*Entry
;
1523 // Make sure parameters are valid
1525 if (Descriptor
== NULL
) {
1526 return EFI_INVALID_PARAMETER
;
1529 CoreAcquireGcdMemoryLock ();
1532 // Search for the list of descriptors that contain BaseAddress
1534 Status
= CoreSearchGcdMapEntry (BaseAddress
, 1, &StartLink
, &EndLink
, &mGcdMemorySpaceMap
);
1535 if (EFI_ERROR (Status
)) {
1536 Status
= EFI_NOT_FOUND
;
1538 ASSERT (StartLink
!= NULL
&& EndLink
!= NULL
);
1540 // Copy the contents of the found descriptor into Descriptor
1542 Entry
= CR (StartLink
, EFI_GCD_MAP_ENTRY
, Link
, EFI_GCD_MAP_SIGNATURE
);
1543 BuildMemoryDescriptor (Descriptor
, Entry
);
1546 CoreReleaseGcdMemoryLock ();
1553 Modifies the attributes for a memory region in the global coherency domain of the
1556 @param BaseAddress Specified start address
1557 @param Length Specified length
1558 @param Attributes Specified attributes
1560 @retval EFI_SUCCESS The attributes were set for the memory region.
1561 @retval EFI_INVALID_PARAMETER Length is zero.
1562 @retval EFI_UNSUPPORTED The processor does not support one or more bytes of the memory
1563 resource range specified by BaseAddress and Length.
1564 @retval EFI_UNSUPPORTED The bit mask of attributes is not support for the memory resource
1565 range specified by BaseAddress and Length.
1566 @retval EFI_ACCESS_DEFINED The attributes for the memory resource range specified by
1567 BaseAddress and Length cannot be modified.
1568 @retval EFI_OUT_OF_RESOURCES There are not enough system resources to modify the attributes of
1569 the memory resource range.
1570 @retval EFI_NOT_AVAILABLE_YET The attributes cannot be set because CPU architectural protocol is
1576 CoreSetMemorySpaceAttributes (
1577 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
1579 IN UINT64 Attributes
1582 DEBUG ((DEBUG_GCD
, "GCD:SetMemorySpaceAttributes(Base=%016lx,Length=%016lx)\n", BaseAddress
, Length
));
1583 DEBUG ((DEBUG_GCD
, " Attributes = %016lx\n", Attributes
));
1585 return CoreConvertSpace (GCD_SET_ATTRIBUTES_MEMORY_OPERATION
, (EFI_GCD_MEMORY_TYPE
) 0, (EFI_GCD_IO_TYPE
) 0, BaseAddress
, Length
, 0, Attributes
);
1590 Modifies the capabilities for a memory region in the global coherency domain of the
1593 @param BaseAddress The physical address that is the start address of a memory region.
1594 @param Length The size in bytes of the memory region.
1595 @param Capabilities The bit mask of capabilities that the memory region supports.
1597 @retval EFI_SUCCESS The capabilities were set for the memory region.
1598 @retval EFI_INVALID_PARAMETER Length is zero.
1599 @retval EFI_UNSUPPORTED The capabilities specified by Capabilities do not include the
1600 memory region attributes currently in use.
1601 @retval EFI_ACCESS_DENIED The capabilities for the memory resource range specified by
1602 BaseAddress and Length cannot be modified.
1603 @retval EFI_OUT_OF_RESOURCES There are not enough system resources to modify the capabilities
1604 of the memory resource range.
1608 CoreSetMemorySpaceCapabilities (
1609 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
1611 IN UINT64 Capabilities
1616 DEBUG ((DEBUG_GCD
, "GCD:CoreSetMemorySpaceCapabilities(Base=%016lx,Length=%016lx)\n", BaseAddress
, Length
));
1617 DEBUG ((DEBUG_GCD
, " Capabilities = %016lx\n", Capabilities
));
1619 Status
= CoreConvertSpace (GCD_SET_CAPABILITIES_MEMORY_OPERATION
, (EFI_GCD_MEMORY_TYPE
) 0, (EFI_GCD_IO_TYPE
) 0, BaseAddress
, Length
, Capabilities
, 0);
1620 if (!EFI_ERROR(Status
)) {
1621 CoreUpdateMemoryAttributes(BaseAddress
, RShiftU64(Length
, EFI_PAGE_SHIFT
), Capabilities
);
1629 Returns a map of the memory resources in the global coherency domain of the
1632 @param NumberOfDescriptors Number of descriptors.
1633 @param MemorySpaceMap Descriptor array
1635 @retval EFI_INVALID_PARAMETER Invalid parameter
1636 @retval EFI_OUT_OF_RESOURCES No enough buffer to allocate
1637 @retval EFI_SUCCESS Successfully get memory space map.
1642 CoreGetMemorySpaceMap (
1643 OUT UINTN
*NumberOfDescriptors
,
1644 OUT EFI_GCD_MEMORY_SPACE_DESCRIPTOR
**MemorySpaceMap
1649 EFI_GCD_MAP_ENTRY
*Entry
;
1650 EFI_GCD_MEMORY_SPACE_DESCRIPTOR
*Descriptor
;
1653 // Make sure parameters are valid
1655 if (NumberOfDescriptors
== NULL
) {
1656 return EFI_INVALID_PARAMETER
;
1658 if (MemorySpaceMap
== NULL
) {
1659 return EFI_INVALID_PARAMETER
;
1662 CoreAcquireGcdMemoryLock ();
1665 // Count the number of descriptors
1667 *NumberOfDescriptors
= CoreCountGcdMapEntry (&mGcdMemorySpaceMap
);
1670 // Allocate the MemorySpaceMap
1672 *MemorySpaceMap
= AllocatePool (*NumberOfDescriptors
* sizeof (EFI_GCD_MEMORY_SPACE_DESCRIPTOR
));
1673 if (*MemorySpaceMap
== NULL
) {
1674 Status
= EFI_OUT_OF_RESOURCES
;
1679 // Fill in the MemorySpaceMap
1681 Descriptor
= *MemorySpaceMap
;
1682 Link
= mGcdMemorySpaceMap
.ForwardLink
;
1683 while (Link
!= &mGcdMemorySpaceMap
) {
1684 Entry
= CR (Link
, EFI_GCD_MAP_ENTRY
, Link
, EFI_GCD_MAP_SIGNATURE
);
1685 BuildMemoryDescriptor (Descriptor
, Entry
);
1687 Link
= Link
->ForwardLink
;
1689 Status
= EFI_SUCCESS
;
1692 CoreReleaseGcdMemoryLock ();
1698 Adds reserved I/O or I/O resources to the global coherency domain of the processor.
1700 @param GcdIoType IO type of the segment.
1701 @param BaseAddress Base address of the segment.
1702 @param Length Length of the segment.
1704 @retval EFI_SUCCESS Merged this segment into GCD map.
1705 @retval EFI_INVALID_PARAMETER Parameter not valid
1711 IN EFI_GCD_IO_TYPE GcdIoType
,
1712 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
1716 DEBUG ((DEBUG_GCD
, "GCD:AddIoSpace(Base=%016lx,Length=%016lx)\n", BaseAddress
, Length
));
1717 DEBUG ((DEBUG_GCD
, " GcdIoType = %a\n", mGcdIoTypeNames
[MIN (GcdIoType
, EfiGcdIoTypeMaximum
)]));
1720 // Make sure parameters are valid
1722 if (GcdIoType
<= EfiGcdIoTypeNonExistent
|| GcdIoType
>= EfiGcdIoTypeMaximum
) {
1723 return EFI_INVALID_PARAMETER
;
1725 return CoreConvertSpace (GCD_ADD_IO_OPERATION
, (EFI_GCD_MEMORY_TYPE
) 0, GcdIoType
, BaseAddress
, Length
, 0, 0);
1730 Allocates nonexistent I/O, reserved I/O, or I/O resources from the global coherency
1731 domain of the processor.
1733 @param GcdAllocateType The type of allocate operation
1734 @param GcdIoType The desired IO type
1735 @param Alignment Align with 2^Alignment
1736 @param Length Length to allocate
1737 @param BaseAddress Base address to allocate
1738 @param ImageHandle The image handle consume the allocated space.
1739 @param DeviceHandle The device handle consume the allocated space.
1741 @retval EFI_INVALID_PARAMETER Invalid parameter.
1742 @retval EFI_NOT_FOUND No descriptor contains the desired space.
1743 @retval EFI_SUCCESS IO space successfully allocated.
1748 CoreAllocateIoSpace (
1749 IN EFI_GCD_ALLOCATE_TYPE GcdAllocateType
,
1750 IN EFI_GCD_IO_TYPE GcdIoType
,
1753 IN OUT EFI_PHYSICAL_ADDRESS
*BaseAddress
,
1754 IN EFI_HANDLE ImageHandle
,
1755 IN EFI_HANDLE DeviceHandle OPTIONAL
1758 DEBUG ((DEBUG_GCD
, "GCD:AllocateIoSpace(Base=%016lx,Length=%016lx)\n", *BaseAddress
, Length
));
1759 DEBUG ((DEBUG_GCD
, " GcdAllocateType = %a\n", mGcdAllocationTypeNames
[MIN (GcdAllocateType
, EfiGcdMaxAllocateType
)]));
1760 DEBUG ((DEBUG_GCD
, " GcdIoType = %a\n", mGcdIoTypeNames
[MIN (GcdIoType
, EfiGcdIoTypeMaximum
)]));
1761 DEBUG ((DEBUG_GCD
, " Alignment = %016lx\n", LShiftU64 (1, Alignment
)));
1762 DEBUG ((DEBUG_GCD
, " ImageHandle = %p\n", ImageHandle
));
1763 DEBUG ((DEBUG_GCD
, " DeviceHandle = %p\n", DeviceHandle
));
1765 return CoreAllocateSpace (
1766 GCD_ALLOCATE_IO_OPERATION
,
1768 (EFI_GCD_MEMORY_TYPE
) 0,
1780 Frees nonexistent I/O, reserved I/O, or I/O resources from the global coherency
1781 domain of the processor.
1783 @param BaseAddress Base address of the segment.
1784 @param Length Length of the segment.
1786 @retval EFI_SUCCESS Space successfully freed.
1792 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
1796 DEBUG ((DEBUG_GCD
, "GCD:FreeIoSpace(Base=%016lx,Length=%016lx)\n", BaseAddress
, Length
));
1798 return CoreConvertSpace (GCD_FREE_IO_OPERATION
, (EFI_GCD_MEMORY_TYPE
) 0, (EFI_GCD_IO_TYPE
) 0, BaseAddress
, Length
, 0, 0);
1803 Removes reserved I/O or I/O resources from the global coherency domain of the
1806 @param BaseAddress Base address of the segment.
1807 @param Length Length of the segment.
1809 @retval EFI_SUCCESS Successfully removed a segment of IO space.
1815 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
1819 DEBUG ((DEBUG_GCD
, "GCD:RemoveIoSpace(Base=%016lx,Length=%016lx)\n", BaseAddress
, Length
));
1821 return CoreConvertSpace (GCD_REMOVE_IO_OPERATION
, (EFI_GCD_MEMORY_TYPE
) 0, (EFI_GCD_IO_TYPE
) 0, BaseAddress
, Length
, 0, 0);
1826 Build a IO descriptor according to an entry.
1828 @param Descriptor The descriptor to be built
1829 @param Entry According to this entry
1834 IN EFI_GCD_IO_SPACE_DESCRIPTOR
*Descriptor
,
1835 IN EFI_GCD_MAP_ENTRY
*Entry
1838 Descriptor
->BaseAddress
= Entry
->BaseAddress
;
1839 Descriptor
->Length
= Entry
->EndAddress
- Entry
->BaseAddress
+ 1;
1840 Descriptor
->GcdIoType
= Entry
->GcdIoType
;
1841 Descriptor
->ImageHandle
= Entry
->ImageHandle
;
1842 Descriptor
->DeviceHandle
= Entry
->DeviceHandle
;
1847 Retrieves the descriptor for an I/O region containing a specified address.
1849 @param BaseAddress Specified start address
1850 @param Descriptor Specified length
1852 @retval EFI_INVALID_PARAMETER Descriptor is NULL.
1853 @retval EFI_SUCCESS Successfully get the IO space descriptor.
1858 CoreGetIoSpaceDescriptor (
1859 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
1860 OUT EFI_GCD_IO_SPACE_DESCRIPTOR
*Descriptor
1864 LIST_ENTRY
*StartLink
;
1865 LIST_ENTRY
*EndLink
;
1866 EFI_GCD_MAP_ENTRY
*Entry
;
1869 // Make sure parameters are valid
1871 if (Descriptor
== NULL
) {
1872 return EFI_INVALID_PARAMETER
;
1875 CoreAcquireGcdIoLock ();
1878 // Search for the list of descriptors that contain BaseAddress
1880 Status
= CoreSearchGcdMapEntry (BaseAddress
, 1, &StartLink
, &EndLink
, &mGcdIoSpaceMap
);
1881 if (EFI_ERROR (Status
)) {
1882 Status
= EFI_NOT_FOUND
;
1884 ASSERT (StartLink
!= NULL
&& EndLink
!= NULL
);
1886 // Copy the contents of the found descriptor into Descriptor
1888 Entry
= CR (StartLink
, EFI_GCD_MAP_ENTRY
, Link
, EFI_GCD_MAP_SIGNATURE
);
1889 BuildIoDescriptor (Descriptor
, Entry
);
1892 CoreReleaseGcdIoLock ();
1899 Returns a map of the I/O resources in the global coherency domain of the processor.
1901 @param NumberOfDescriptors Number of descriptors.
1902 @param IoSpaceMap Descriptor array
1904 @retval EFI_INVALID_PARAMETER Invalid parameter
1905 @retval EFI_OUT_OF_RESOURCES No enough buffer to allocate
1906 @retval EFI_SUCCESS Successfully get IO space map.
1912 OUT UINTN
*NumberOfDescriptors
,
1913 OUT EFI_GCD_IO_SPACE_DESCRIPTOR
**IoSpaceMap
1918 EFI_GCD_MAP_ENTRY
*Entry
;
1919 EFI_GCD_IO_SPACE_DESCRIPTOR
*Descriptor
;
1922 // Make sure parameters are valid
1924 if (NumberOfDescriptors
== NULL
) {
1925 return EFI_INVALID_PARAMETER
;
1927 if (IoSpaceMap
== NULL
) {
1928 return EFI_INVALID_PARAMETER
;
1931 CoreAcquireGcdIoLock ();
1934 // Count the number of descriptors
1936 *NumberOfDescriptors
= CoreCountGcdMapEntry (&mGcdIoSpaceMap
);
1939 // Allocate the IoSpaceMap
1941 *IoSpaceMap
= AllocatePool (*NumberOfDescriptors
* sizeof (EFI_GCD_IO_SPACE_DESCRIPTOR
));
1942 if (*IoSpaceMap
== NULL
) {
1943 Status
= EFI_OUT_OF_RESOURCES
;
1948 // Fill in the IoSpaceMap
1950 Descriptor
= *IoSpaceMap
;
1951 Link
= mGcdIoSpaceMap
.ForwardLink
;
1952 while (Link
!= &mGcdIoSpaceMap
) {
1953 Entry
= CR (Link
, EFI_GCD_MAP_ENTRY
, Link
, EFI_GCD_MAP_SIGNATURE
);
1954 BuildIoDescriptor (Descriptor
, Entry
);
1956 Link
= Link
->ForwardLink
;
1958 Status
= EFI_SUCCESS
;
1961 CoreReleaseGcdIoLock ();
1967 Converts a Resource Descriptor HOB attributes mask to an EFI Memory Descriptor
1970 @param GcdMemoryType Type of resource in the GCD memory map.
1971 @param Attributes The attribute mask in the Resource Descriptor
1974 @return The capabilities mask for an EFI Memory Descriptor.
1978 CoreConvertResourceDescriptorHobAttributesToCapabilities (
1979 EFI_GCD_MEMORY_TYPE GcdMemoryType
,
1983 UINT64 Capabilities
;
1984 GCD_ATTRIBUTE_CONVERSION_ENTRY
*Conversion
;
1987 // Convert the Resource HOB Attributes to an EFI Memory Capabilities mask
1989 for (Capabilities
= 0, Conversion
= mAttributeConversionTable
; Conversion
->Attribute
!= 0; Conversion
++) {
1990 if (Conversion
->Memory
|| (GcdMemoryType
!= EfiGcdMemoryTypeSystemMemory
)) {
1991 if (Attributes
& Conversion
->Attribute
) {
1992 Capabilities
|= Conversion
->Capability
;
1997 return Capabilities
;
2002 External function. Initializes memory services based on the memory
2003 descriptor HOBs. This function is responsible for priming the memory
2004 map, so memory allocations and resource allocations can be made.
2005 The first part of this function can not depend on any memory services
2006 until at least one memory descriptor is provided to the memory services.
2008 @param HobStart The start address of the HOB.
2009 @param MemoryBaseAddress Start address of memory region found to init DXE
2011 @param MemoryLength Length of memory region found to init DXE core.
2013 @retval EFI_SUCCESS Memory services successfully initialized.
2017 CoreInitializeMemoryServices (
2019 OUT EFI_PHYSICAL_ADDRESS
*MemoryBaseAddress
,
2020 OUT UINT64
*MemoryLength
2023 EFI_PEI_HOB_POINTERS Hob
;
2024 EFI_MEMORY_TYPE_INFORMATION
*EfiMemoryTypeInformation
;
2027 EFI_HOB_HANDOFF_INFO_TABLE
*PhitHob
;
2028 EFI_HOB_RESOURCE_DESCRIPTOR
*ResourceHob
;
2029 EFI_HOB_RESOURCE_DESCRIPTOR
*PhitResourceHob
;
2030 EFI_PHYSICAL_ADDRESS BaseAddress
;
2033 UINT64 Capabilities
;
2034 EFI_PHYSICAL_ADDRESS MaxMemoryBaseAddress
;
2035 UINT64 MaxMemoryLength
;
2036 UINT64 MaxMemoryAttributes
;
2037 EFI_PHYSICAL_ADDRESS TestedMemoryBaseAddress
;
2038 UINT64 TestedMemoryLength
;
2039 EFI_PHYSICAL_ADDRESS HighAddress
;
2040 EFI_HOB_GUID_TYPE
*GuidHob
;
2041 UINT32 ReservedCodePageNumber
;
2044 // Point at the first HOB. This must be the PHIT HOB.
2046 Hob
.Raw
= *HobStart
;
2047 ASSERT (GET_HOB_TYPE (Hob
) == EFI_HOB_TYPE_HANDOFF
);
2050 // Initialize the spin locks and maps in the memory services.
2051 // Also fill in the memory services into the EFI Boot Services Table
2053 CoreInitializePool ();
2056 // Initialize Local Variables
2058 PhitResourceHob
= NULL
;
2063 MaxMemoryBaseAddress
= 0;
2064 MaxMemoryLength
= 0;
2065 MaxMemoryAttributes
= 0;
2068 // Cache the PHIT HOB for later use
2070 PhitHob
= Hob
.HandoffInformationTable
;
2072 if (PcdGet64(PcdLoadModuleAtFixAddressEnable
) != 0) {
2073 ReservedCodePageNumber
= PcdGet32(PcdLoadFixAddressRuntimeCodePageNumber
);
2074 ReservedCodePageNumber
+= PcdGet32(PcdLoadFixAddressBootTimeCodePageNumber
);
2077 // cache the Top address for loading modules at Fixed Address
2079 gLoadModuleAtFixAddressConfigurationTable
.DxeCodeTopAddress
= PhitHob
->EfiMemoryTop
2080 + EFI_PAGES_TO_SIZE(ReservedCodePageNumber
);
2083 // See if a Memory Type Information HOB is available
2085 GuidHob
= GetFirstGuidHob (&gEfiMemoryTypeInformationGuid
);
2086 if (GuidHob
!= NULL
) {
2087 EfiMemoryTypeInformation
= GET_GUID_HOB_DATA (GuidHob
);
2088 DataSize
= GET_GUID_HOB_DATA_SIZE (GuidHob
);
2089 if (EfiMemoryTypeInformation
!= NULL
&& DataSize
> 0 && DataSize
<= (EfiMaxMemoryType
+ 1) * sizeof (EFI_MEMORY_TYPE_INFORMATION
)) {
2090 CopyMem (&gMemoryTypeInformation
, EfiMemoryTypeInformation
, DataSize
);
2095 // Find the Resource Descriptor HOB that contains PHIT range EfiFreeMemoryBottom..EfiFreeMemoryTop
2099 for (Hob
.Raw
= *HobStart
; !END_OF_HOB_LIST(Hob
); Hob
.Raw
= GET_NEXT_HOB(Hob
)) {
2101 // Skip all HOBs except Resource Descriptor HOBs
2103 if (GET_HOB_TYPE (Hob
) != EFI_HOB_TYPE_RESOURCE_DESCRIPTOR
) {
2108 // Skip Resource Descriptor HOBs that do not describe tested system memory
2110 ResourceHob
= Hob
.ResourceDescriptor
;
2111 if (ResourceHob
->ResourceType
!= EFI_RESOURCE_SYSTEM_MEMORY
) {
2114 if ((ResourceHob
->ResourceAttribute
& MEMORY_ATTRIBUTE_MASK
) != TESTED_MEMORY_ATTRIBUTES
) {
2119 // Skip Resource Descriptor HOBs that do not contain the PHIT range EfiFreeMemoryBottom..EfiFreeMemoryTop
2121 if (PhitHob
->EfiFreeMemoryBottom
< ResourceHob
->PhysicalStart
) {
2124 if (PhitHob
->EfiFreeMemoryTop
> (ResourceHob
->PhysicalStart
+ ResourceHob
->ResourceLength
)) {
2129 // Cache the resource descriptor HOB for the memory region described by the PHIT HOB
2131 PhitResourceHob
= ResourceHob
;
2135 // Compute range between PHIT EfiFreeMemoryTop and the end of the Resource Descriptor HOB
2137 Attributes
= PhitResourceHob
->ResourceAttribute
;
2138 BaseAddress
= PageAlignAddress (PhitHob
->EfiMemoryTop
);
2139 Length
= PageAlignLength (ResourceHob
->PhysicalStart
+ ResourceHob
->ResourceLength
- BaseAddress
);
2140 if (Length
< MINIMUM_INITIAL_MEMORY_SIZE
) {
2142 // If that range is not large enough to intialize the DXE Core, then
2143 // Compute range between PHIT EfiFreeMemoryBottom and PHIT EfiFreeMemoryTop
2145 BaseAddress
= PageAlignAddress (PhitHob
->EfiFreeMemoryBottom
);
2146 Length
= PageAlignLength (PhitHob
->EfiFreeMemoryTop
- BaseAddress
);
2147 if (Length
< MINIMUM_INITIAL_MEMORY_SIZE
) {
2149 // If that range is not large enough to intialize the DXE Core, then
2150 // Compute range between the start of the Resource Descriptor HOB and the start of the HOB List
2152 BaseAddress
= PageAlignAddress (ResourceHob
->PhysicalStart
);
2153 Length
= PageAlignLength ((UINT64
)((UINTN
)*HobStart
- BaseAddress
));
2160 // Assert if a resource descriptor HOB for the memory region described by the PHIT was not found
2165 // Search all the resource descriptor HOBs from the highest possible addresses down for a memory
2166 // region that is big enough to initialize the DXE core. Always skip the PHIT Resource HOB.
2167 // The max address must be within the physically addressible range for the processor.
2169 HighAddress
= MAX_ADDRESS
;
2170 for (Hob
.Raw
= *HobStart
; !END_OF_HOB_LIST(Hob
); Hob
.Raw
= GET_NEXT_HOB(Hob
)) {
2172 // Skip the Resource Descriptor HOB that contains the PHIT
2174 if (Hob
.ResourceDescriptor
== PhitResourceHob
) {
2178 // Skip all HOBs except Resource Descriptor HOBs
2180 if (GET_HOB_TYPE (Hob
) != EFI_HOB_TYPE_RESOURCE_DESCRIPTOR
) {
2185 // Skip Resource Descriptor HOBs that do not describe tested system memory below MAX_ADDRESS
2187 ResourceHob
= Hob
.ResourceDescriptor
;
2188 if (ResourceHob
->ResourceType
!= EFI_RESOURCE_SYSTEM_MEMORY
) {
2191 if ((ResourceHob
->ResourceAttribute
& MEMORY_ATTRIBUTE_MASK
) != TESTED_MEMORY_ATTRIBUTES
) {
2194 if ((ResourceHob
->PhysicalStart
+ ResourceHob
->ResourceLength
) > (EFI_PHYSICAL_ADDRESS
)MAX_ADDRESS
) {
2199 // Skip Resource Descriptor HOBs that are below a previously found Resource Descriptor HOB
2201 if (HighAddress
!= (EFI_PHYSICAL_ADDRESS
)MAX_ADDRESS
&& ResourceHob
->PhysicalStart
<= HighAddress
) {
2206 // Skip Resource Descriptor HOBs that are not large enough to initilize the DXE Core
2208 TestedMemoryBaseAddress
= PageAlignAddress (ResourceHob
->PhysicalStart
);
2209 TestedMemoryLength
= PageAlignLength (ResourceHob
->PhysicalStart
+ ResourceHob
->ResourceLength
- TestedMemoryBaseAddress
);
2210 if (TestedMemoryLength
< MINIMUM_INITIAL_MEMORY_SIZE
) {
2215 // Save the Resource Descriptor HOB context that is large enough to initilize the DXE Core
2217 MaxMemoryBaseAddress
= TestedMemoryBaseAddress
;
2218 MaxMemoryLength
= TestedMemoryLength
;
2219 MaxMemoryAttributes
= ResourceHob
->ResourceAttribute
;
2220 HighAddress
= ResourceHob
->PhysicalStart
;
2224 // If Length is not large enough to initialize the DXE Core or a Resource
2225 // Descriptor HOB was found above the PHIT HOB that is large enough to initialize
2226 // the DXE Core, then use the range described by the Resource Descriptor
2227 // HOB that was found above the PHIT HOB.
2229 if ((Length
< MINIMUM_INITIAL_MEMORY_SIZE
) ||
2230 (MaxMemoryBaseAddress
> BaseAddress
&& MaxMemoryLength
>= MINIMUM_INITIAL_MEMORY_SIZE
)) {
2231 BaseAddress
= MaxMemoryBaseAddress
;
2232 Length
= MaxMemoryLength
;
2233 Attributes
= MaxMemoryAttributes
;
2237 // If no memory regions are found that are big enough to initialize the DXE core, then ASSERT().
2239 ASSERT (Length
>= MINIMUM_INITIAL_MEMORY_SIZE
);
2242 // Convert the Resource HOB Attributes to an EFI Memory Capabilities mask
2244 Capabilities
= CoreConvertResourceDescriptorHobAttributesToCapabilities (EfiGcdMemoryTypeSystemMemory
, Attributes
);
2247 // Declare the very first memory region, so the EFI Memory Services are available.
2249 CoreAddMemoryDescriptor (
2250 EfiConventionalMemory
,
2252 RShiftU64 (Length
, EFI_PAGE_SHIFT
),
2256 *MemoryBaseAddress
= BaseAddress
;
2257 *MemoryLength
= Length
;
2264 External function. Initializes the GCD and memory services based on the memory
2265 descriptor HOBs. This function is responsible for priming the GCD map and the
2266 memory map, so memory allocations and resource allocations can be made. The
2267 HobStart will be relocated to a pool buffer.
2269 @param HobStart The start address of the HOB
2270 @param MemoryBaseAddress Start address of memory region found to init DXE
2272 @param MemoryLength Length of memory region found to init DXE core.
2274 @retval EFI_SUCCESS GCD services successfully initialized.
2278 CoreInitializeGcdServices (
2279 IN OUT VOID
**HobStart
,
2280 IN EFI_PHYSICAL_ADDRESS MemoryBaseAddress
,
2281 IN UINT64 MemoryLength
2284 EFI_PEI_HOB_POINTERS Hob
;
2286 EFI_HOB_HANDOFF_INFO_TABLE
*PhitHob
;
2287 UINT8 SizeOfMemorySpace
;
2288 UINT8 SizeOfIoSpace
;
2289 EFI_HOB_RESOURCE_DESCRIPTOR
*ResourceHob
;
2290 EFI_PHYSICAL_ADDRESS BaseAddress
;
2293 EFI_GCD_MAP_ENTRY
*Entry
;
2294 EFI_GCD_MEMORY_TYPE GcdMemoryType
;
2295 EFI_GCD_IO_TYPE GcdIoType
;
2296 EFI_GCD_MEMORY_SPACE_DESCRIPTOR Descriptor
;
2297 EFI_HOB_MEMORY_ALLOCATION
*MemoryHob
;
2298 EFI_HOB_FIRMWARE_VOLUME
*FirmwareVolumeHob
;
2299 UINTN NumberOfDescriptors
;
2300 EFI_GCD_MEMORY_SPACE_DESCRIPTOR
*MemorySpaceMap
;
2302 UINT64 Capabilities
;
2303 EFI_HOB_CPU
* CpuHob
;
2306 // Cache the PHIT HOB for later use
2308 PhitHob
= (EFI_HOB_HANDOFF_INFO_TABLE
*)(*HobStart
);
2311 // Get the number of address lines in the I/O and Memory space for the CPU
2313 CpuHob
= GetFirstHob (EFI_HOB_TYPE_CPU
);
2314 ASSERT (CpuHob
!= NULL
);
2315 SizeOfMemorySpace
= CpuHob
->SizeOfMemorySpace
;
2316 SizeOfIoSpace
= CpuHob
->SizeOfIoSpace
;
2319 // Initialize the GCD Memory Space Map
2321 Entry
= AllocateCopyPool (sizeof (EFI_GCD_MAP_ENTRY
), &mGcdMemorySpaceMapEntryTemplate
);
2322 ASSERT (Entry
!= NULL
);
2324 Entry
->EndAddress
= LShiftU64 (1, SizeOfMemorySpace
) - 1;
2326 InsertHeadList (&mGcdMemorySpaceMap
, &Entry
->Link
);
2328 CoreDumpGcdMemorySpaceMap (TRUE
);
2331 // Initialize the GCD I/O Space Map
2333 Entry
= AllocateCopyPool (sizeof (EFI_GCD_MAP_ENTRY
), &mGcdIoSpaceMapEntryTemplate
);
2334 ASSERT (Entry
!= NULL
);
2336 Entry
->EndAddress
= LShiftU64 (1, SizeOfIoSpace
) - 1;
2338 InsertHeadList (&mGcdIoSpaceMap
, &Entry
->Link
);
2340 CoreDumpGcdIoSpaceMap (TRUE
);
2343 // Walk the HOB list and add all resource descriptors to the GCD
2345 for (Hob
.Raw
= *HobStart
; !END_OF_HOB_LIST(Hob
); Hob
.Raw
= GET_NEXT_HOB(Hob
)) {
2347 GcdMemoryType
= EfiGcdMemoryTypeNonExistent
;
2348 GcdIoType
= EfiGcdIoTypeNonExistent
;
2350 if (GET_HOB_TYPE (Hob
) == EFI_HOB_TYPE_RESOURCE_DESCRIPTOR
) {
2352 ResourceHob
= Hob
.ResourceDescriptor
;
2354 switch (ResourceHob
->ResourceType
) {
2355 case EFI_RESOURCE_SYSTEM_MEMORY
:
2356 if ((ResourceHob
->ResourceAttribute
& MEMORY_ATTRIBUTE_MASK
) == TESTED_MEMORY_ATTRIBUTES
) {
2357 GcdMemoryType
= EfiGcdMemoryTypeSystemMemory
;
2359 if ((ResourceHob
->ResourceAttribute
& MEMORY_ATTRIBUTE_MASK
) == INITIALIZED_MEMORY_ATTRIBUTES
) {
2360 GcdMemoryType
= EfiGcdMemoryTypeReserved
;
2362 if ((ResourceHob
->ResourceAttribute
& MEMORY_ATTRIBUTE_MASK
) == PRESENT_MEMORY_ATTRIBUTES
) {
2363 GcdMemoryType
= EfiGcdMemoryTypeReserved
;
2365 if ((ResourceHob
->ResourceAttribute
& EFI_RESOURCE_ATTRIBUTE_PERSISTENT
) == EFI_RESOURCE_ATTRIBUTE_PERSISTENT
) {
2366 GcdMemoryType
= EfiGcdMemoryTypePersistentMemory
;
2369 case EFI_RESOURCE_MEMORY_MAPPED_IO
:
2370 case EFI_RESOURCE_FIRMWARE_DEVICE
:
2371 GcdMemoryType
= EfiGcdMemoryTypeMemoryMappedIo
;
2373 case EFI_RESOURCE_MEMORY_MAPPED_IO_PORT
:
2374 case EFI_RESOURCE_MEMORY_RESERVED
:
2375 GcdMemoryType
= EfiGcdMemoryTypeReserved
;
2377 case EFI_RESOURCE_IO
:
2378 GcdIoType
= EfiGcdIoTypeIo
;
2380 case EFI_RESOURCE_IO_RESERVED
:
2381 GcdIoType
= EfiGcdIoTypeReserved
;
2385 if (GcdMemoryType
!= EfiGcdMemoryTypeNonExistent
) {
2387 // Validate the Resource HOB Attributes
2389 CoreValidateResourceDescriptorHobAttributes (ResourceHob
->ResourceAttribute
);
2392 // Convert the Resource HOB Attributes to an EFI Memory Capabilities mask
2394 Capabilities
= CoreConvertResourceDescriptorHobAttributesToCapabilities (
2396 ResourceHob
->ResourceAttribute
2399 Status
= CoreInternalAddMemorySpace (
2401 ResourceHob
->PhysicalStart
,
2402 ResourceHob
->ResourceLength
,
2407 if (GcdIoType
!= EfiGcdIoTypeNonExistent
) {
2408 Status
= CoreAddIoSpace (
2410 ResourceHob
->PhysicalStart
,
2411 ResourceHob
->ResourceLength
2418 // Allocate first memory region from the GCD by the DXE core
2420 Status
= CoreAllocateMemorySpace (
2421 EfiGcdAllocateAddress
,
2422 EfiGcdMemoryTypeSystemMemory
,
2426 gDxeCoreImageHandle
,
2431 // Walk the HOB list and allocate all memory space that is consumed by memory allocation HOBs,
2432 // and Firmware Volume HOBs. Also update the EFI Memory Map with the memory allocation HOBs.
2434 for (Hob
.Raw
= *HobStart
; !END_OF_HOB_LIST(Hob
); Hob
.Raw
= GET_NEXT_HOB(Hob
)) {
2435 if (GET_HOB_TYPE (Hob
) == EFI_HOB_TYPE_MEMORY_ALLOCATION
) {
2436 MemoryHob
= Hob
.MemoryAllocation
;
2437 BaseAddress
= MemoryHob
->AllocDescriptor
.MemoryBaseAddress
;
2438 Status
= CoreGetMemorySpaceDescriptor (BaseAddress
, &Descriptor
);
2439 if (!EFI_ERROR (Status
)) {
2440 Status
= CoreAllocateMemorySpace (
2441 EfiGcdAllocateAddress
,
2442 Descriptor
.GcdMemoryType
,
2444 MemoryHob
->AllocDescriptor
.MemoryLength
,
2446 gDxeCoreImageHandle
,
2449 if (!EFI_ERROR (Status
) && Descriptor
.GcdMemoryType
== EfiGcdMemoryTypeSystemMemory
) {
2450 CoreAddMemoryDescriptor (
2451 MemoryHob
->AllocDescriptor
.MemoryType
,
2452 MemoryHob
->AllocDescriptor
.MemoryBaseAddress
,
2453 RShiftU64 (MemoryHob
->AllocDescriptor
.MemoryLength
, EFI_PAGE_SHIFT
),
2454 Descriptor
.Capabilities
& (~EFI_MEMORY_RUNTIME
)
2460 if (GET_HOB_TYPE (Hob
) == EFI_HOB_TYPE_FV
) {
2461 FirmwareVolumeHob
= Hob
.FirmwareVolume
;
2462 BaseAddress
= FirmwareVolumeHob
->BaseAddress
;
2463 Status
= CoreAllocateMemorySpace (
2464 EfiGcdAllocateAddress
,
2465 EfiGcdMemoryTypeMemoryMappedIo
,
2467 FirmwareVolumeHob
->Length
,
2469 gDxeCoreImageHandle
,
2476 // Relocate HOB List to an allocated pool buffer.
2478 NewHobList
= AllocateCopyPool (
2479 (UINTN
)PhitHob
->EfiFreeMemoryBottom
- (UINTN
)(*HobStart
),
2482 ASSERT (NewHobList
!= NULL
);
2484 *HobStart
= NewHobList
;
2485 gHobList
= NewHobList
;
2488 // Add and allocate the remaining unallocated system memory to the memory services.
2490 Status
= CoreGetMemorySpaceMap (&NumberOfDescriptors
, &MemorySpaceMap
);
2491 ASSERT (Status
== EFI_SUCCESS
);
2493 for (Index
= 0; Index
< NumberOfDescriptors
; Index
++) {
2494 if (MemorySpaceMap
[Index
].GcdMemoryType
== EfiGcdMemoryTypeSystemMemory
) {
2495 if (MemorySpaceMap
[Index
].ImageHandle
== NULL
) {
2496 BaseAddress
= PageAlignAddress (MemorySpaceMap
[Index
].BaseAddress
);
2497 Length
= PageAlignLength (MemorySpaceMap
[Index
].BaseAddress
+ MemorySpaceMap
[Index
].Length
- BaseAddress
);
2498 if (Length
== 0 || MemorySpaceMap
[Index
].BaseAddress
+ MemorySpaceMap
[Index
].Length
< BaseAddress
) {
2501 CoreAddMemoryDescriptor (
2502 EfiConventionalMemory
,
2504 RShiftU64 (Length
, EFI_PAGE_SHIFT
),
2505 MemorySpaceMap
[Index
].Capabilities
& (~EFI_MEMORY_RUNTIME
)
2507 Status
= CoreAllocateMemorySpace (
2508 EfiGcdAllocateAddress
,
2509 EfiGcdMemoryTypeSystemMemory
,
2513 gDxeCoreImageHandle
,
2519 CoreFreePool (MemorySpaceMap
);