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 - 2011, 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 )
32 #define TESTED_MEMORY_ATTRIBUTES (EFI_RESOURCE_ATTRIBUTE_PRESENT | \
33 EFI_RESOURCE_ATTRIBUTE_INITIALIZED | \
34 EFI_RESOURCE_ATTRIBUTE_TESTED )
36 #define INITIALIZED_MEMORY_ATTRIBUTES (EFI_RESOURCE_ATTRIBUTE_PRESENT | \
37 EFI_RESOURCE_ATTRIBUTE_INITIALIZED )
39 #define PRESENT_MEMORY_ATTRIBUTES (EFI_RESOURCE_ATTRIBUTE_PRESENT)
41 #define INVALID_CPU_ARCH_ATTRIBUTES 0xffffffff
46 EFI_LOCK mGcdMemorySpaceLock
= EFI_INITIALIZE_LOCK_VARIABLE (TPL_NOTIFY
);
47 EFI_LOCK mGcdIoSpaceLock
= EFI_INITIALIZE_LOCK_VARIABLE (TPL_NOTIFY
);
48 LIST_ENTRY mGcdMemorySpaceMap
= INITIALIZE_LIST_HEAD_VARIABLE (mGcdMemorySpaceMap
);
49 LIST_ENTRY mGcdIoSpaceMap
= INITIALIZE_LIST_HEAD_VARIABLE (mGcdIoSpaceMap
);
51 EFI_GCD_MAP_ENTRY mGcdMemorySpaceMapEntryTemplate
= {
52 EFI_GCD_MAP_SIGNATURE
,
61 EfiGcdMemoryTypeNonExistent
,
67 EFI_GCD_MAP_ENTRY mGcdIoSpaceMapEntryTemplate
= {
68 EFI_GCD_MAP_SIGNATURE
,
77 (EFI_GCD_MEMORY_TYPE
) 0,
78 EfiGcdIoTypeNonExistent
,
83 GCD_ATTRIBUTE_CONVERSION_ENTRY mAttributeConversionTable
[] = {
84 { EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE
, EFI_MEMORY_UC
, TRUE
},
85 { EFI_RESOURCE_ATTRIBUTE_UNCACHED_EXPORTED
, EFI_MEMORY_UCE
, TRUE
},
86 { EFI_RESOURCE_ATTRIBUTE_WRITE_COMBINEABLE
, EFI_MEMORY_WC
, TRUE
},
87 { EFI_RESOURCE_ATTRIBUTE_WRITE_THROUGH_CACHEABLE
, EFI_MEMORY_WT
, TRUE
},
88 { EFI_RESOURCE_ATTRIBUTE_WRITE_BACK_CACHEABLE
, EFI_MEMORY_WB
, TRUE
},
89 { EFI_RESOURCE_ATTRIBUTE_READ_PROTECTED
, EFI_MEMORY_RP
, TRUE
},
90 { EFI_RESOURCE_ATTRIBUTE_WRITE_PROTECTED
, EFI_MEMORY_WP
, TRUE
},
91 { EFI_RESOURCE_ATTRIBUTE_EXECUTION_PROTECTED
, EFI_MEMORY_XP
, TRUE
},
92 { EFI_RESOURCE_ATTRIBUTE_PRESENT
, EFI_MEMORY_PRESENT
, FALSE
},
93 { EFI_RESOURCE_ATTRIBUTE_INITIALIZED
, EFI_MEMORY_INITIALIZED
, FALSE
},
94 { EFI_RESOURCE_ATTRIBUTE_TESTED
, EFI_MEMORY_TESTED
, FALSE
},
99 /// Lookup table used to print GCD Memory Space Map
101 GLOBAL_REMOVE_IF_UNREFERENCED CONST CHAR8
*mGcdMemoryTypeNames
[] = {
102 "NonExist ", // EfiGcdMemoryTypeNonExistent
103 "Reserved ", // EfiGcdMemoryTypeReserved
104 "SystemMem", // EfiGcdMemoryTypeSystemMemory
105 "MMIO ", // EfiGcdMemoryTypeMemoryMappedIo
106 "Unknown " // EfiGcdMemoryTypeMaximum
110 /// Lookup table used to print GCD I/O Space Map
112 GLOBAL_REMOVE_IF_UNREFERENCED CONST CHAR8
*mGcdIoTypeNames
[] = {
113 "NonExist", // EfiGcdIoTypeNonExistent
114 "Reserved", // EfiGcdIoTypeReserved
115 "I/O ", // EfiGcdIoTypeIo
116 "Unknown " // EfiGcdIoTypeMaximum
120 /// Lookup table used to print GCD Allocation Types
122 GLOBAL_REMOVE_IF_UNREFERENCED CONST CHAR8
*mGcdAllocationTypeNames
[] = {
123 "AnySearchBottomUp ", // EfiGcdAllocateAnySearchBottomUp
124 "MaxAddressSearchBottomUp ", // EfiGcdAllocateMaxAddressSearchBottomUp
125 "AtAddress ", // EfiGcdAllocateAddress
126 "AnySearchTopDown ", // EfiGcdAllocateAnySearchTopDown
127 "MaxAddressSearchTopDown ", // EfiGcdAllocateMaxAddressSearchTopDown
128 "Unknown " // EfiGcdMaxAllocateType
132 Dump the entire contents if the GCD Memory Space Map using DEBUG() macros when
133 PcdDebugPrintErrorLevel has the DEBUG_GCD bit set.
138 CoreDumpGcdMemorySpaceMap (
143 UINTN NumberOfDescriptors
;
144 EFI_GCD_MEMORY_SPACE_DESCRIPTOR
*MemorySpaceMap
;
147 Status
= CoreGetMemorySpaceMap (&NumberOfDescriptors
, &MemorySpaceMap
);
148 ASSERT_EFI_ERROR (Status
);
150 DEBUG ((DEBUG_GCD
, "GCDMemType Range Capabilities Attributes \n"));
151 DEBUG ((DEBUG_GCD
, "========== ================================= ================ ================\n"));
152 for (Index
= 0; Index
< NumberOfDescriptors
; Index
++) {
153 DEBUG ((DEBUG_GCD
, "%a %016lx-%016lx %016lx %016lx%c\n",
154 mGcdMemoryTypeNames
[MIN (MemorySpaceMap
[Index
].GcdMemoryType
, EfiGcdMemoryTypeMaximum
)],
155 MemorySpaceMap
[Index
].BaseAddress
,
156 MemorySpaceMap
[Index
].BaseAddress
+ MemorySpaceMap
[Index
].Length
- 1,
157 MemorySpaceMap
[Index
].Capabilities
,
158 MemorySpaceMap
[Index
].Attributes
,
159 MemorySpaceMap
[Index
].ImageHandle
== NULL
? ' ' : '*'
162 DEBUG ((DEBUG_GCD
, "\n"));
163 FreePool (MemorySpaceMap
);
167 Dump the entire contents if the GCD I/O Space Map using DEBUG() macros when
168 PcdDebugPrintErrorLevel has the DEBUG_GCD bit set.
173 CoreDumpGcdIoSpaceMap (
178 UINTN NumberOfDescriptors
;
179 EFI_GCD_IO_SPACE_DESCRIPTOR
*IoSpaceMap
;
182 Status
= CoreGetIoSpaceMap (&NumberOfDescriptors
, &IoSpaceMap
);
183 ASSERT_EFI_ERROR (Status
);
185 DEBUG ((DEBUG_GCD
, "GCDIoType Range \n"));
186 DEBUG ((DEBUG_GCD
, "========== =================================\n"));
187 for (Index
= 0; Index
< NumberOfDescriptors
; Index
++) {
188 DEBUG ((DEBUG_GCD
, "%a %016lx-%016lx%c\n",
189 mGcdIoTypeNames
[MIN (IoSpaceMap
[Index
].GcdIoType
, EfiGcdIoTypeMaximum
)],
190 IoSpaceMap
[Index
].BaseAddress
,
191 IoSpaceMap
[Index
].BaseAddress
+ IoSpaceMap
[Index
].Length
- 1,
192 IoSpaceMap
[Index
].ImageHandle
== NULL
? ' ' : '*'
195 DEBUG ((DEBUG_GCD
, "\n"));
196 FreePool (IoSpaceMap
);
202 Acquire memory lock on mGcdMemorySpaceLock.
206 CoreAcquireGcdMemoryLock (
210 CoreAcquireLock (&mGcdMemorySpaceLock
);
216 Release memory lock on mGcdMemorySpaceLock.
220 CoreReleaseGcdMemoryLock (
224 CoreReleaseLock (&mGcdMemorySpaceLock
);
230 Acquire memory lock on mGcdIoSpaceLock.
234 CoreAcquireGcdIoLock (
238 CoreAcquireLock (&mGcdIoSpaceLock
);
243 Release memory lock on mGcdIoSpaceLock.
247 CoreReleaseGcdIoLock (
251 CoreReleaseLock (&mGcdIoSpaceLock
);
257 // GCD Initialization Worker Functions
260 Aligns a value to the specified boundary.
262 @param Value 64 bit value to align
263 @param Alignment Log base 2 of the boundary to align Value to
264 @param RoundUp TRUE if Value is to be rounded up to the nearest
265 aligned boundary. FALSE is Value is to be
266 rounded down to the nearest aligned boundary.
268 @return A 64 bit value is the aligned to the value nearest Value with an alignment by Alignment.
278 UINT64 AlignmentMask
;
280 AlignmentMask
= LShiftU64 (1, Alignment
) - 1;
282 Value
+= AlignmentMask
;
284 return Value
& (~AlignmentMask
);
289 Aligns address to the page boundary.
291 @param Value 64 bit address to align
293 @return A 64 bit value is the aligned to the value nearest Value with an alignment by Alignment.
301 return AlignValue (Value
, EFI_PAGE_SHIFT
, TRUE
);
306 Aligns length to the page boundary.
308 @param Value 64 bit length to align
310 @return A 64 bit value is the aligned to the value nearest Value with an alignment by Alignment.
318 return AlignValue (Value
, EFI_PAGE_SHIFT
, FALSE
);
322 // GCD Memory Space Worker Functions
326 Allocate pool for two entries.
328 @param TopEntry An entry of GCD map
329 @param BottomEntry An entry of GCD map
331 @retval EFI_OUT_OF_RESOURCES No enough buffer to be allocated.
332 @retval EFI_SUCCESS Both entries successfully allocated.
336 CoreAllocateGcdMapEntry (
337 IN OUT EFI_GCD_MAP_ENTRY
**TopEntry
,
338 IN OUT EFI_GCD_MAP_ENTRY
**BottomEntry
341 *TopEntry
= AllocateZeroPool (sizeof (EFI_GCD_MAP_ENTRY
));
342 if (*TopEntry
== NULL
) {
343 return EFI_OUT_OF_RESOURCES
;
346 *BottomEntry
= AllocateZeroPool (sizeof (EFI_GCD_MAP_ENTRY
));
347 if (*BottomEntry
== NULL
) {
348 CoreFreePool (*TopEntry
);
349 return EFI_OUT_OF_RESOURCES
;
357 Internal function. Inserts a new descriptor into a sorted list
359 @param Link The linked list to insert the range BaseAddress
361 @param Entry A pointer to the entry that is inserted
362 @param BaseAddress The base address of the new range
363 @param Length The length of the new range in bytes
364 @param TopEntry Top pad entry to insert if needed.
365 @param BottomEntry Bottom pad entry to insert if needed.
367 @retval EFI_SUCCESS The new range was inserted into the linked list
371 CoreInsertGcdMapEntry (
373 IN EFI_GCD_MAP_ENTRY
*Entry
,
374 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
376 IN EFI_GCD_MAP_ENTRY
*TopEntry
,
377 IN EFI_GCD_MAP_ENTRY
*BottomEntry
380 ASSERT (Length
!= 0);
381 ASSERT (TopEntry
->Signature
== 0);
382 ASSERT (BottomEntry
->Signature
== 0);
384 if (BaseAddress
> Entry
->BaseAddress
) {
385 CopyMem (BottomEntry
, Entry
, sizeof (EFI_GCD_MAP_ENTRY
));
386 Entry
->BaseAddress
= BaseAddress
;
387 BottomEntry
->EndAddress
= BaseAddress
- 1;
388 InsertTailList (Link
, &BottomEntry
->Link
);
391 if ((BaseAddress
+ Length
- 1) < Entry
->EndAddress
) {
392 CopyMem (TopEntry
, Entry
, sizeof (EFI_GCD_MAP_ENTRY
));
393 TopEntry
->BaseAddress
= BaseAddress
+ Length
;
394 Entry
->EndAddress
= BaseAddress
+ Length
- 1;
395 InsertHeadList (Link
, &TopEntry
->Link
);
403 Merge the Gcd region specified by Link and its adjacent entry.
405 @param Link Specify the entry to be merged (with its
407 @param Forward Direction (forward or backward).
410 @retval EFI_SUCCESS Successfully returned.
411 @retval EFI_UNSUPPORTED These adjacent regions could not merge.
415 CoreMergeGcdMapEntry (
421 LIST_ENTRY
*AdjacentLink
;
422 EFI_GCD_MAP_ENTRY
*Entry
;
423 EFI_GCD_MAP_ENTRY
*AdjacentEntry
;
426 // Get adjacent entry
429 AdjacentLink
= Link
->ForwardLink
;
431 AdjacentLink
= Link
->BackLink
;
435 // If AdjacentLink is the head of the list, then no merge can be performed
437 if (AdjacentLink
== Map
) {
441 Entry
= CR (Link
, EFI_GCD_MAP_ENTRY
, Link
, EFI_GCD_MAP_SIGNATURE
);
442 AdjacentEntry
= CR (AdjacentLink
, EFI_GCD_MAP_ENTRY
, Link
, EFI_GCD_MAP_SIGNATURE
);
444 if (Entry
->Capabilities
!= AdjacentEntry
->Capabilities
) {
445 return EFI_UNSUPPORTED
;
447 if (Entry
->Attributes
!= AdjacentEntry
->Attributes
) {
448 return EFI_UNSUPPORTED
;
450 if (Entry
->GcdMemoryType
!= AdjacentEntry
->GcdMemoryType
) {
451 return EFI_UNSUPPORTED
;
453 if (Entry
->GcdIoType
!= AdjacentEntry
->GcdIoType
) {
454 return EFI_UNSUPPORTED
;
456 if (Entry
->ImageHandle
!= AdjacentEntry
->ImageHandle
) {
457 return EFI_UNSUPPORTED
;
459 if (Entry
->DeviceHandle
!= AdjacentEntry
->DeviceHandle
) {
460 return EFI_UNSUPPORTED
;
464 Entry
->EndAddress
= AdjacentEntry
->EndAddress
;
466 Entry
->BaseAddress
= AdjacentEntry
->BaseAddress
;
468 RemoveEntryList (AdjacentLink
);
469 CoreFreePool (AdjacentEntry
);
476 Merge adjacent entries on total chain.
478 @param TopEntry Top entry of GCD map.
479 @param BottomEntry Bottom entry of GCD map.
480 @param StartLink Start link of the list for this loop.
481 @param EndLink End link of the list for this loop.
484 @retval EFI_SUCCESS GCD map successfully cleaned up.
488 CoreCleanupGcdMapEntry (
489 IN EFI_GCD_MAP_ENTRY
*TopEntry
,
490 IN EFI_GCD_MAP_ENTRY
*BottomEntry
,
491 IN LIST_ENTRY
*StartLink
,
492 IN LIST_ENTRY
*EndLink
,
498 if (TopEntry
->Signature
== 0) {
499 CoreFreePool (TopEntry
);
501 if (BottomEntry
->Signature
== 0) {
502 CoreFreePool (BottomEntry
);
506 while (Link
!= EndLink
->ForwardLink
) {
507 CoreMergeGcdMapEntry (Link
, FALSE
, Map
);
508 Link
= Link
->ForwardLink
;
510 CoreMergeGcdMapEntry (EndLink
, TRUE
, Map
);
517 Search a segment of memory space in GCD map. The result is a range of GCD entry list.
519 @param BaseAddress The start address of the segment.
520 @param Length The length of the segment.
521 @param StartLink The first GCD entry involves this segment of
523 @param EndLink The first GCD entry involves this segment of
525 @param Map Points to the start entry to search.
527 @retval EFI_SUCCESS Successfully found the entry.
528 @retval EFI_NOT_FOUND Not found.
532 CoreSearchGcdMapEntry (
533 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
535 OUT LIST_ENTRY
**StartLink
,
536 OUT LIST_ENTRY
**EndLink
,
541 EFI_GCD_MAP_ENTRY
*Entry
;
543 ASSERT (Length
!= 0);
548 Link
= Map
->ForwardLink
;
549 while (Link
!= Map
) {
550 Entry
= CR (Link
, EFI_GCD_MAP_ENTRY
, Link
, EFI_GCD_MAP_SIGNATURE
);
551 if (BaseAddress
>= Entry
->BaseAddress
&& BaseAddress
<= Entry
->EndAddress
) {
554 if (*StartLink
!= NULL
) {
555 if ((BaseAddress
+ Length
- 1) >= Entry
->BaseAddress
&&
556 (BaseAddress
+ Length
- 1) <= Entry
->EndAddress
) {
561 Link
= Link
->ForwardLink
;
564 return EFI_NOT_FOUND
;
569 Count the amount of GCD map entries.
571 @param Map Points to the start entry to do the count loop.
577 CoreCountGcdMapEntry (
585 Link
= Map
->ForwardLink
;
586 while (Link
!= Map
) {
588 Link
= Link
->ForwardLink
;
597 Return the memory attribute specified by Attributes
599 @param Attributes A num with some attribute bits on.
601 @return The enum value of memory attribute.
605 ConverToCpuArchAttributes (
609 if ( (Attributes
& EFI_MEMORY_UC
) == EFI_MEMORY_UC
) {
610 return EFI_MEMORY_UC
;
613 if ( (Attributes
& EFI_MEMORY_WC
) == EFI_MEMORY_WC
) {
614 return EFI_MEMORY_WC
;
617 if ( (Attributes
& EFI_MEMORY_WT
) == EFI_MEMORY_WT
) {
618 return EFI_MEMORY_WT
;
621 if ( (Attributes
& EFI_MEMORY_WB
) == EFI_MEMORY_WB
) {
622 return EFI_MEMORY_WB
;
625 if ( (Attributes
& EFI_MEMORY_WP
) == EFI_MEMORY_WP
) {
626 return EFI_MEMORY_WP
;
629 return INVALID_CPU_ARCH_ATTRIBUTES
;
635 Do operation on a segment of memory space specified (add, free, remove, change attribute ...).
637 @param Operation The type of the operation
638 @param GcdMemoryType Additional information for the operation
639 @param GcdIoType Additional information for the operation
640 @param BaseAddress Start address of the segment
641 @param Length length of the segment
642 @param Capabilities The alterable attributes of a newly added entry
643 @param Attributes The attributes needs to be set
645 @retval EFI_INVALID_PARAMETER Length is 0 or address (length) not aligned when
647 @retval EFI_SUCCESS Action successfully done.
648 @retval EFI_UNSUPPORTED Could not find the proper descriptor on this
649 segment or set an upsupported attribute.
650 @retval EFI_ACCESS_DENIED Operate on an space non-exist or is used for an
652 @retval EFI_NOT_FOUND Free a non-using space or remove a non-exist
654 @retval EFI_OUT_OF_RESOURCES No buffer could be allocated.
660 IN EFI_GCD_MEMORY_TYPE GcdMemoryType
,
661 IN EFI_GCD_IO_TYPE GcdIoType
,
662 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
664 IN UINT64 Capabilities
,
671 EFI_GCD_MAP_ENTRY
*Entry
;
672 EFI_GCD_MAP_ENTRY
*TopEntry
;
673 EFI_GCD_MAP_ENTRY
*BottomEntry
;
674 LIST_ENTRY
*StartLink
;
676 UINT64 CpuArchAttributes
;
680 DEBUG ((DEBUG_GCD
, " Status = %r\n", EFI_INVALID_PARAMETER
));
682 return EFI_INVALID_PARAMETER
;
686 if ((Operation
& GCD_MEMORY_SPACE_OPERATION
) != 0) {
687 CoreAcquireGcdMemoryLock ();
688 Map
= &mGcdMemorySpaceMap
;
689 } else if ((Operation
& GCD_IO_SPACE_OPERATION
) != 0) {
690 CoreAcquireGcdIoLock ();
691 Map
= &mGcdIoSpaceMap
;
697 // Search for the list of descriptors that cover the range BaseAddress to BaseAddress+Length
699 Status
= CoreSearchGcdMapEntry (BaseAddress
, Length
, &StartLink
, &EndLink
, Map
);
700 if (EFI_ERROR (Status
)) {
701 Status
= EFI_UNSUPPORTED
;
705 ASSERT (StartLink
!= NULL
&& EndLink
!= NULL
);
708 // Verify that the list of descriptors are unallocated non-existent memory.
711 while (Link
!= EndLink
->ForwardLink
) {
712 Entry
= CR (Link
, EFI_GCD_MAP_ENTRY
, Link
, EFI_GCD_MAP_SIGNATURE
);
717 case GCD_ADD_MEMORY_OPERATION
:
718 if (Entry
->GcdMemoryType
!= EfiGcdMemoryTypeNonExistent
||
719 Entry
->ImageHandle
!= NULL
) {
720 Status
= EFI_ACCESS_DENIED
;
724 case GCD_ADD_IO_OPERATION
:
725 if (Entry
->GcdIoType
!= EfiGcdIoTypeNonExistent
||
726 Entry
->ImageHandle
!= NULL
) {
727 Status
= EFI_ACCESS_DENIED
;
734 case GCD_FREE_MEMORY_OPERATION
:
735 case GCD_FREE_IO_OPERATION
:
736 if (Entry
->ImageHandle
== NULL
) {
737 Status
= EFI_NOT_FOUND
;
744 case GCD_REMOVE_MEMORY_OPERATION
:
745 if (Entry
->GcdMemoryType
== EfiGcdMemoryTypeNonExistent
) {
746 Status
= EFI_NOT_FOUND
;
749 if (Entry
->ImageHandle
!= NULL
) {
750 Status
= EFI_ACCESS_DENIED
;
754 case GCD_REMOVE_IO_OPERATION
:
755 if (Entry
->GcdIoType
== EfiGcdIoTypeNonExistent
) {
756 Status
= EFI_NOT_FOUND
;
759 if (Entry
->ImageHandle
!= NULL
) {
760 Status
= EFI_ACCESS_DENIED
;
765 // Set attribute operations
767 case GCD_SET_ATTRIBUTES_MEMORY_OPERATION
:
768 if ((Attributes
& EFI_MEMORY_RUNTIME
) != 0) {
769 if ((BaseAddress
& EFI_PAGE_MASK
) != 0 || (Length
& EFI_PAGE_MASK
) != 0) {
770 Status
= EFI_INVALID_PARAMETER
;
774 if ((Entry
->Capabilities
& Attributes
) != Attributes
) {
775 Status
= EFI_UNSUPPORTED
;
780 Link
= Link
->ForwardLink
;
784 // Allocate work space to perform this operation
786 Status
= CoreAllocateGcdMapEntry (&TopEntry
, &BottomEntry
);
787 if (EFI_ERROR (Status
)) {
788 Status
= EFI_OUT_OF_RESOURCES
;
791 ASSERT (TopEntry
!= NULL
&& BottomEntry
!= NULL
);
793 if (Operation
== GCD_SET_ATTRIBUTES_MEMORY_OPERATION
) {
795 // Call CPU Arch Protocol to attempt to set attributes on the range
797 CpuArchAttributes
= ConverToCpuArchAttributes (Attributes
);
798 if (CpuArchAttributes
!= INVALID_CPU_ARCH_ATTRIBUTES
) {
800 Status
= gCpu
->SetMemoryAttributes (
806 if (EFI_ERROR (Status
)) {
814 // Convert/Insert the list of descriptors from StartLink to EndLink
817 while (Link
!= EndLink
->ForwardLink
) {
818 Entry
= CR (Link
, EFI_GCD_MAP_ENTRY
, Link
, EFI_GCD_MAP_SIGNATURE
);
819 CoreInsertGcdMapEntry (Link
, Entry
, BaseAddress
, Length
, TopEntry
, BottomEntry
);
824 case GCD_ADD_MEMORY_OPERATION
:
825 Entry
->GcdMemoryType
= GcdMemoryType
;
826 if (GcdMemoryType
== EfiGcdMemoryTypeMemoryMappedIo
) {
827 Entry
->Capabilities
= Capabilities
| EFI_MEMORY_RUNTIME
| EFI_MEMORY_PORT_IO
;
829 Entry
->Capabilities
= Capabilities
| EFI_MEMORY_RUNTIME
;
832 case GCD_ADD_IO_OPERATION
:
833 Entry
->GcdIoType
= GcdIoType
;
838 case GCD_FREE_MEMORY_OPERATION
:
839 case GCD_FREE_IO_OPERATION
:
840 Entry
->ImageHandle
= NULL
;
841 Entry
->DeviceHandle
= NULL
;
846 case GCD_REMOVE_MEMORY_OPERATION
:
847 Entry
->GcdMemoryType
= EfiGcdMemoryTypeNonExistent
;
848 Entry
->Capabilities
= 0;
850 case GCD_REMOVE_IO_OPERATION
:
851 Entry
->GcdIoType
= EfiGcdIoTypeNonExistent
;
854 // Set attribute operations
856 case GCD_SET_ATTRIBUTES_MEMORY_OPERATION
:
857 Entry
->Attributes
= Attributes
;
860 Link
= Link
->ForwardLink
;
866 Status
= CoreCleanupGcdMapEntry (TopEntry
, BottomEntry
, StartLink
, EndLink
, Map
);
870 DEBUG ((DEBUG_GCD
, " Status = %r\n", Status
));
873 if ((Operation
& GCD_MEMORY_SPACE_OPERATION
) != 0) {
874 CoreReleaseGcdMemoryLock ();
877 // Do not dump GCD Memory Space Map for GCD changes below 16 MB
879 if (BaseAddress
>= BASE_16MB
) {
880 CoreDumpGcdMemorySpaceMap ();
884 if ((Operation
& GCD_IO_SPACE_OPERATION
) != 0) {
885 CoreReleaseGcdIoLock ();
887 CoreDumpGcdIoSpaceMap ();
896 Check whether an entry could be used to allocate space.
898 @param Operation Allocate memory or IO
899 @param Entry The entry to be tested
900 @param GcdMemoryType The desired memory type
901 @param GcdIoType The desired IO type
903 @retval EFI_NOT_FOUND The memory type does not match or there's an
904 image handle on the entry.
905 @retval EFI_UNSUPPORTED The operation unsupported.
906 @retval EFI_SUCCESS It's ok for this entry to be used to allocate
911 CoreAllocateSpaceCheckEntry (
913 IN EFI_GCD_MAP_ENTRY
*Entry
,
914 IN EFI_GCD_MEMORY_TYPE GcdMemoryType
,
915 IN EFI_GCD_IO_TYPE GcdIoType
918 if (Entry
->ImageHandle
!= NULL
) {
919 return EFI_NOT_FOUND
;
922 case GCD_ALLOCATE_MEMORY_OPERATION
:
923 if (Entry
->GcdMemoryType
!= GcdMemoryType
) {
924 return EFI_NOT_FOUND
;
927 case GCD_ALLOCATE_IO_OPERATION
:
928 if (Entry
->GcdIoType
!= GcdIoType
) {
929 return EFI_NOT_FOUND
;
933 return EFI_UNSUPPORTED
;
940 Allocate space on specified address and length.
942 @param Operation The type of operation (memory or IO)
943 @param GcdAllocateType The type of allocate operation
944 @param GcdMemoryType The desired memory type
945 @param GcdIoType The desired IO type
946 @param Alignment Align with 2^Alignment
947 @param Length Length to allocate
948 @param BaseAddress Base address to allocate
949 @param ImageHandle The image handle consume the allocated space.
950 @param DeviceHandle The device handle consume the allocated space.
952 @retval EFI_INVALID_PARAMETER Invalid parameter.
953 @retval EFI_NOT_FOUND No descriptor for the desired space exists.
954 @retval EFI_SUCCESS Space successfully allocated.
960 IN EFI_GCD_ALLOCATE_TYPE GcdAllocateType
,
961 IN EFI_GCD_MEMORY_TYPE GcdMemoryType
,
962 IN EFI_GCD_IO_TYPE GcdIoType
,
965 IN OUT EFI_PHYSICAL_ADDRESS
*BaseAddress
,
966 IN EFI_HANDLE ImageHandle
,
967 IN EFI_HANDLE DeviceHandle OPTIONAL
971 EFI_PHYSICAL_ADDRESS AlignmentMask
;
972 EFI_PHYSICAL_ADDRESS MaxAddress
;
976 EFI_GCD_MAP_ENTRY
*Entry
;
977 EFI_GCD_MAP_ENTRY
*TopEntry
;
978 EFI_GCD_MAP_ENTRY
*BottomEntry
;
979 LIST_ENTRY
*StartLink
;
984 // Make sure parameters are valid
986 if (GcdAllocateType
< 0 || GcdAllocateType
>= EfiGcdMaxAllocateType
) {
988 DEBUG ((DEBUG_GCD
, " Status = %r\n", EFI_INVALID_PARAMETER
));
990 return EFI_INVALID_PARAMETER
;
992 if (GcdMemoryType
< 0 || GcdMemoryType
>= EfiGcdMemoryTypeMaximum
) {
994 DEBUG ((DEBUG_GCD
, " Status = %r\n", EFI_INVALID_PARAMETER
));
996 return EFI_INVALID_PARAMETER
;
998 if (GcdIoType
< 0 || GcdIoType
>= EfiGcdIoTypeMaximum
) {
1000 DEBUG ((DEBUG_GCD
, " Status = %r\n", EFI_INVALID_PARAMETER
));
1002 return EFI_INVALID_PARAMETER
;
1004 if (BaseAddress
== NULL
) {
1005 DEBUG_CODE_BEGIN ();
1006 DEBUG ((DEBUG_GCD
, " Status = %r\n", EFI_INVALID_PARAMETER
));
1008 return EFI_INVALID_PARAMETER
;
1010 if (ImageHandle
== NULL
) {
1011 DEBUG_CODE_BEGIN ();
1012 DEBUG ((DEBUG_GCD
, " Status = %r\n", EFI_INVALID_PARAMETER
));
1014 return EFI_INVALID_PARAMETER
;
1016 if (Alignment
>= 64) {
1017 DEBUG_CODE_BEGIN ();
1018 DEBUG ((DEBUG_GCD
, " Status = %r\n", EFI_NOT_FOUND
));
1020 return EFI_NOT_FOUND
;
1023 DEBUG_CODE_BEGIN ();
1024 DEBUG ((DEBUG_GCD
, " Status = %r\n", EFI_INVALID_PARAMETER
));
1026 return EFI_INVALID_PARAMETER
;
1030 if ((Operation
& GCD_MEMORY_SPACE_OPERATION
) != 0) {
1031 CoreAcquireGcdMemoryLock ();
1032 Map
= &mGcdMemorySpaceMap
;
1033 } else if ((Operation
& GCD_IO_SPACE_OPERATION
) != 0) {
1034 CoreAcquireGcdIoLock ();
1035 Map
= &mGcdIoSpaceMap
;
1044 // Compute alignment bit mask
1046 AlignmentMask
= LShiftU64 (1, Alignment
) - 1;
1048 if (GcdAllocateType
== EfiGcdAllocateAddress
) {
1050 // Verify that the BaseAddress passed in is aligned correctly
1052 if ((*BaseAddress
& AlignmentMask
) != 0) {
1053 Status
= EFI_NOT_FOUND
;
1058 // Search for the list of descriptors that cover the range BaseAddress to BaseAddress+Length
1060 Status
= CoreSearchGcdMapEntry (*BaseAddress
, Length
, &StartLink
, &EndLink
, Map
);
1061 if (EFI_ERROR (Status
)) {
1062 Status
= EFI_NOT_FOUND
;
1065 ASSERT (StartLink
!= NULL
&& EndLink
!= NULL
);
1068 // Verify that the list of descriptors are unallocated memory matching GcdMemoryType.
1071 while (Link
!= EndLink
->ForwardLink
) {
1072 Entry
= CR (Link
, EFI_GCD_MAP_ENTRY
, Link
, EFI_GCD_MAP_SIGNATURE
);
1073 Link
= Link
->ForwardLink
;
1074 Status
= CoreAllocateSpaceCheckEntry (Operation
, Entry
, GcdMemoryType
, GcdIoType
);
1075 if (EFI_ERROR (Status
)) {
1082 Entry
= CR (Map
->BackLink
, EFI_GCD_MAP_ENTRY
, Link
, EFI_GCD_MAP_SIGNATURE
);
1085 // Compute the maximum address to use in the search algorithm
1087 if (GcdAllocateType
== EfiGcdAllocateMaxAddressSearchBottomUp
||
1088 GcdAllocateType
== EfiGcdAllocateMaxAddressSearchTopDown
) {
1089 MaxAddress
= *BaseAddress
;
1091 MaxAddress
= Entry
->EndAddress
;
1095 // Verify that the list of descriptors are unallocated memory matching GcdMemoryType.
1097 if (GcdAllocateType
== EfiGcdAllocateMaxAddressSearchTopDown
||
1098 GcdAllocateType
== EfiGcdAllocateAnySearchTopDown
) {
1099 Link
= Map
->BackLink
;
1101 Link
= Map
->ForwardLink
;
1103 while (Link
!= Map
) {
1104 Entry
= CR (Link
, EFI_GCD_MAP_ENTRY
, Link
, EFI_GCD_MAP_SIGNATURE
);
1106 if (GcdAllocateType
== EfiGcdAllocateMaxAddressSearchTopDown
||
1107 GcdAllocateType
== EfiGcdAllocateAnySearchTopDown
) {
1108 Link
= Link
->BackLink
;
1110 Link
= Link
->ForwardLink
;
1113 Status
= CoreAllocateSpaceCheckEntry (Operation
, Entry
, GcdMemoryType
, GcdIoType
);
1114 if (EFI_ERROR (Status
)) {
1118 if (GcdAllocateType
== EfiGcdAllocateMaxAddressSearchTopDown
||
1119 GcdAllocateType
== EfiGcdAllocateAnySearchTopDown
) {
1120 if ((Entry
->BaseAddress
+ Length
) > MaxAddress
) {
1123 if (Length
> (Entry
->EndAddress
+ 1)) {
1124 Status
= EFI_NOT_FOUND
;
1127 if (Entry
->EndAddress
> MaxAddress
) {
1128 *BaseAddress
= MaxAddress
;
1130 *BaseAddress
= Entry
->EndAddress
;
1132 *BaseAddress
= (*BaseAddress
+ 1 - Length
) & (~AlignmentMask
);
1134 *BaseAddress
= (Entry
->BaseAddress
+ AlignmentMask
) & (~AlignmentMask
);
1135 if ((*BaseAddress
+ Length
- 1) > MaxAddress
) {
1136 Status
= EFI_NOT_FOUND
;
1142 // Search for the list of descriptors that cover the range BaseAddress to BaseAddress+Length
1144 Status
= CoreSearchGcdMapEntry (*BaseAddress
, Length
, &StartLink
, &EndLink
, Map
);
1145 if (EFI_ERROR (Status
)) {
1146 Status
= EFI_NOT_FOUND
;
1149 ASSERT (StartLink
!= NULL
&& EndLink
!= NULL
);
1153 // Verify that the list of descriptors are unallocated memory matching GcdMemoryType.
1156 SubLink
= StartLink
;
1157 while (SubLink
!= EndLink
->ForwardLink
) {
1158 Entry
= CR (SubLink
, EFI_GCD_MAP_ENTRY
, Link
, EFI_GCD_MAP_SIGNATURE
);
1159 Status
= CoreAllocateSpaceCheckEntry (Operation
, Entry
, GcdMemoryType
, GcdIoType
);
1160 if (EFI_ERROR (Status
)) {
1165 SubLink
= SubLink
->ForwardLink
;
1173 Status
= EFI_NOT_FOUND
;
1178 // Allocate work space to perform this operation
1180 Status
= CoreAllocateGcdMapEntry (&TopEntry
, &BottomEntry
);
1181 if (EFI_ERROR (Status
)) {
1182 Status
= EFI_OUT_OF_RESOURCES
;
1185 ASSERT (TopEntry
!= NULL
&& BottomEntry
!= NULL
);
1188 // Convert/Insert the list of descriptors from StartLink to EndLink
1191 while (Link
!= EndLink
->ForwardLink
) {
1192 Entry
= CR (Link
, EFI_GCD_MAP_ENTRY
, Link
, EFI_GCD_MAP_SIGNATURE
);
1193 CoreInsertGcdMapEntry (Link
, Entry
, *BaseAddress
, Length
, TopEntry
, BottomEntry
);
1194 Entry
->ImageHandle
= ImageHandle
;
1195 Entry
->DeviceHandle
= DeviceHandle
;
1196 Link
= Link
->ForwardLink
;
1202 Status
= CoreCleanupGcdMapEntry (TopEntry
, BottomEntry
, StartLink
, EndLink
, Map
);
1205 DEBUG_CODE_BEGIN ();
1206 DEBUG ((DEBUG_GCD
, " Status = %r", Status
));
1207 if (!EFI_ERROR (Status
)) {
1208 DEBUG ((DEBUG_GCD
, " (BaseAddress = %016lx)\n", *BaseAddress
));
1210 DEBUG ((DEBUG_GCD
, "\n"));
1213 if ((Operation
& GCD_MEMORY_SPACE_OPERATION
) != 0) {
1214 CoreReleaseGcdMemoryLock ();
1215 DEBUG_CODE_BEGIN ();
1217 // Do not dump GCD Memory Space Map for GCD changes below 16 MB
1219 if (*BaseAddress
>= BASE_16MB
) {
1220 CoreDumpGcdMemorySpaceMap ();
1224 if ((Operation
& GCD_IO_SPACE_OPERATION
) !=0) {
1225 CoreReleaseGcdIoLock ();
1226 DEBUG_CODE_BEGIN ();
1227 CoreDumpGcdIoSpaceMap ();
1236 Add a segment of memory to GCD map.
1238 @param GcdMemoryType Memory type of the segment.
1239 @param BaseAddress Base address of the segment.
1240 @param Length Length of the segment.
1241 @param Capabilities alterable attributes of the segment.
1243 @retval EFI_INVALID_PARAMETER Invalid parameters.
1244 @retval EFI_SUCCESS Successfully add a segment of memory space.
1248 CoreInternalAddMemorySpace (
1249 IN EFI_GCD_MEMORY_TYPE GcdMemoryType
,
1250 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
1252 IN UINT64 Capabilities
1255 DEBUG ((DEBUG_GCD
, "GCD:AddMemorySpace(Base=%016lx,Length=%016lx)\n", BaseAddress
, Length
));
1256 DEBUG ((DEBUG_GCD
, " GcdMemoryType = %a\n", mGcdMemoryTypeNames
[MIN (GcdMemoryType
, EfiGcdMemoryTypeMaximum
)]));
1257 DEBUG ((DEBUG_GCD
, " Capabilities = %016lx\n", Capabilities
));
1260 // Make sure parameters are valid
1262 if (GcdMemoryType
<= EfiGcdMemoryTypeNonExistent
|| GcdMemoryType
>= EfiGcdMemoryTypeMaximum
) {
1263 return EFI_INVALID_PARAMETER
;
1266 return CoreConvertSpace (GCD_ADD_MEMORY_OPERATION
, GcdMemoryType
, (EFI_GCD_IO_TYPE
) 0, BaseAddress
, Length
, Capabilities
, 0);
1270 // GCD Core Services
1274 Allocates nonexistent memory, reserved memory, system memory, or memorymapped
1275 I/O resources from the global coherency domain of the processor.
1277 @param GcdAllocateType The type of allocate operation
1278 @param GcdMemoryType The desired memory type
1279 @param Alignment Align with 2^Alignment
1280 @param Length Length to allocate
1281 @param BaseAddress Base address to allocate
1282 @param ImageHandle The image handle consume the allocated space.
1283 @param DeviceHandle The device handle consume the allocated space.
1285 @retval EFI_INVALID_PARAMETER Invalid parameter.
1286 @retval EFI_NOT_FOUND No descriptor contains the desired space.
1287 @retval EFI_SUCCESS Memory space successfully allocated.
1292 CoreAllocateMemorySpace (
1293 IN EFI_GCD_ALLOCATE_TYPE GcdAllocateType
,
1294 IN EFI_GCD_MEMORY_TYPE GcdMemoryType
,
1297 IN OUT EFI_PHYSICAL_ADDRESS
*BaseAddress
,
1298 IN EFI_HANDLE ImageHandle
,
1299 IN EFI_HANDLE DeviceHandle OPTIONAL
1302 DEBUG ((DEBUG_GCD
, "GCD:AllocateMemorySpace(Base=%016lx,Length=%016lx)\n", *BaseAddress
, Length
));
1303 DEBUG ((DEBUG_GCD
, " GcdAllocateType = %a\n", mGcdAllocationTypeNames
[MIN (GcdAllocateType
, EfiGcdMaxAllocateType
)]));
1304 DEBUG ((DEBUG_GCD
, " GcdMemoryType = %a\n", mGcdMemoryTypeNames
[MIN (GcdMemoryType
, EfiGcdMemoryTypeMaximum
)]));
1305 DEBUG ((DEBUG_GCD
, " Alignment = %016lx\n", LShiftU64 (1, Alignment
)));
1306 DEBUG ((DEBUG_GCD
, " ImageHandle = %p\n", ImageHandle
));
1307 DEBUG ((DEBUG_GCD
, " DeviceHandle = %p\n", DeviceHandle
));
1309 return CoreAllocateSpace (
1310 GCD_ALLOCATE_MEMORY_OPERATION
,
1313 (EFI_GCD_IO_TYPE
) 0,
1324 Adds reserved memory, system memory, or memory-mapped I/O resources to the
1325 global coherency domain of the processor.
1327 @param GcdMemoryType Memory type of the memory space.
1328 @param BaseAddress Base address of the memory space.
1329 @param Length Length of the memory space.
1330 @param Capabilities alterable attributes of the memory space.
1332 @retval EFI_SUCCESS Merged this memory space into GCD map.
1337 CoreAddMemorySpace (
1338 IN EFI_GCD_MEMORY_TYPE GcdMemoryType
,
1339 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
1341 IN UINT64 Capabilities
1345 EFI_PHYSICAL_ADDRESS PageBaseAddress
;
1348 Status
= CoreInternalAddMemorySpace (GcdMemoryType
, BaseAddress
, Length
, Capabilities
);
1350 if (!EFI_ERROR (Status
) && GcdMemoryType
== EfiGcdMemoryTypeSystemMemory
) {
1352 PageBaseAddress
= PageAlignLength (BaseAddress
);
1353 PageLength
= PageAlignLength (BaseAddress
+ Length
- PageBaseAddress
);
1355 Status
= CoreAllocateMemorySpace (
1356 EfiGcdAllocateAddress
,
1361 gDxeCoreImageHandle
,
1365 if (!EFI_ERROR (Status
)) {
1366 CoreAddMemoryDescriptor (
1367 EfiConventionalMemory
,
1369 RShiftU64 (PageLength
, EFI_PAGE_SHIFT
),
1373 for (; PageLength
!= 0; PageLength
-= EFI_PAGE_SIZE
, PageBaseAddress
+= EFI_PAGE_SIZE
) {
1374 Status
= CoreAllocateMemorySpace (
1375 EfiGcdAllocateAddress
,
1380 gDxeCoreImageHandle
,
1384 if (!EFI_ERROR (Status
)) {
1385 CoreAddMemoryDescriptor (
1386 EfiConventionalMemory
,
1400 Frees nonexistent memory, reserved memory, system memory, or memory-mapped
1401 I/O resources from the global coherency domain of the processor.
1403 @param BaseAddress Base address of the memory space.
1404 @param Length Length of the memory space.
1406 @retval EFI_SUCCESS Space successfully freed.
1411 CoreFreeMemorySpace (
1412 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
1416 DEBUG ((DEBUG_GCD
, "GCD:FreeMemorySpace(Base=%016lx,Length=%016lx)\n", BaseAddress
, Length
));
1418 return CoreConvertSpace (GCD_FREE_MEMORY_OPERATION
, (EFI_GCD_MEMORY_TYPE
) 0, (EFI_GCD_IO_TYPE
) 0, BaseAddress
, Length
, 0, 0);
1423 Removes reserved memory, system memory, or memory-mapped I/O resources from
1424 the global coherency domain of the processor.
1426 @param BaseAddress Base address of the memory space.
1427 @param Length Length of the memory space.
1429 @retval EFI_SUCCESS Successfully remove a segment of memory space.
1434 CoreRemoveMemorySpace (
1435 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
1439 DEBUG ((DEBUG_GCD
, "GCD:RemoveMemorySpace(Base=%016lx,Length=%016lx)\n", BaseAddress
, Length
));
1441 return CoreConvertSpace (GCD_REMOVE_MEMORY_OPERATION
, (EFI_GCD_MEMORY_TYPE
) 0, (EFI_GCD_IO_TYPE
) 0, BaseAddress
, Length
, 0, 0);
1446 Build a memory descriptor according to an entry.
1448 @param Descriptor The descriptor to be built
1449 @param Entry According to this entry
1453 BuildMemoryDescriptor (
1454 IN OUT EFI_GCD_MEMORY_SPACE_DESCRIPTOR
*Descriptor
,
1455 IN EFI_GCD_MAP_ENTRY
*Entry
1458 Descriptor
->BaseAddress
= Entry
->BaseAddress
;
1459 Descriptor
->Length
= Entry
->EndAddress
- Entry
->BaseAddress
+ 1;
1460 Descriptor
->Capabilities
= Entry
->Capabilities
;
1461 Descriptor
->Attributes
= Entry
->Attributes
;
1462 Descriptor
->GcdMemoryType
= Entry
->GcdMemoryType
;
1463 Descriptor
->ImageHandle
= Entry
->ImageHandle
;
1464 Descriptor
->DeviceHandle
= Entry
->DeviceHandle
;
1469 Retrieves the descriptor for a memory region containing a specified address.
1471 @param BaseAddress Specified start address
1472 @param Descriptor Specified length
1474 @retval EFI_INVALID_PARAMETER Invalid parameter
1475 @retval EFI_SUCCESS Successfully get memory space descriptor.
1480 CoreGetMemorySpaceDescriptor (
1481 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
1482 OUT EFI_GCD_MEMORY_SPACE_DESCRIPTOR
*Descriptor
1486 LIST_ENTRY
*StartLink
;
1487 LIST_ENTRY
*EndLink
;
1488 EFI_GCD_MAP_ENTRY
*Entry
;
1491 // Make sure parameters are valid
1493 if (Descriptor
== NULL
) {
1494 return EFI_INVALID_PARAMETER
;
1497 CoreAcquireGcdMemoryLock ();
1500 // Search for the list of descriptors that contain BaseAddress
1502 Status
= CoreSearchGcdMapEntry (BaseAddress
, 1, &StartLink
, &EndLink
, &mGcdMemorySpaceMap
);
1503 if (EFI_ERROR (Status
)) {
1504 Status
= EFI_NOT_FOUND
;
1506 ASSERT (StartLink
!= NULL
&& EndLink
!= NULL
);
1508 // Copy the contents of the found descriptor into Descriptor
1510 Entry
= CR (StartLink
, EFI_GCD_MAP_ENTRY
, Link
, EFI_GCD_MAP_SIGNATURE
);
1511 BuildMemoryDescriptor (Descriptor
, Entry
);
1514 CoreReleaseGcdMemoryLock ();
1521 Modifies the attributes for a memory region in the global coherency domain of the
1524 @param BaseAddress Specified start address
1525 @param Length Specified length
1526 @param Attributes Specified attributes
1528 @retval EFI_SUCCESS Successfully set attribute of a segment of
1534 CoreSetMemorySpaceAttributes (
1535 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
1537 IN UINT64 Attributes
1540 DEBUG ((DEBUG_GCD
, "GCD:SetMemorySpaceAttributes(Base=%016lx,Length=%016lx)\n", BaseAddress
, Length
));
1541 DEBUG ((DEBUG_GCD
, " Attributes = %016lx\n", Attributes
));
1543 return CoreConvertSpace (GCD_SET_ATTRIBUTES_MEMORY_OPERATION
, (EFI_GCD_MEMORY_TYPE
) 0, (EFI_GCD_IO_TYPE
) 0, BaseAddress
, Length
, 0, Attributes
);
1548 Returns a map of the memory resources in the global coherency domain of the
1551 @param NumberOfDescriptors Number of descriptors.
1552 @param MemorySpaceMap Descriptor array
1554 @retval EFI_INVALID_PARAMETER Invalid parameter
1555 @retval EFI_OUT_OF_RESOURCES No enough buffer to allocate
1556 @retval EFI_SUCCESS Successfully get memory space map.
1561 CoreGetMemorySpaceMap (
1562 OUT UINTN
*NumberOfDescriptors
,
1563 OUT EFI_GCD_MEMORY_SPACE_DESCRIPTOR
**MemorySpaceMap
1568 EFI_GCD_MAP_ENTRY
*Entry
;
1569 EFI_GCD_MEMORY_SPACE_DESCRIPTOR
*Descriptor
;
1572 // Make sure parameters are valid
1574 if (NumberOfDescriptors
== NULL
) {
1575 return EFI_INVALID_PARAMETER
;
1577 if (MemorySpaceMap
== NULL
) {
1578 return EFI_INVALID_PARAMETER
;
1581 CoreAcquireGcdMemoryLock ();
1584 // Count the number of descriptors
1586 *NumberOfDescriptors
= CoreCountGcdMapEntry (&mGcdMemorySpaceMap
);
1589 // Allocate the MemorySpaceMap
1591 *MemorySpaceMap
= AllocatePool (*NumberOfDescriptors
* sizeof (EFI_GCD_MEMORY_SPACE_DESCRIPTOR
));
1592 if (*MemorySpaceMap
== NULL
) {
1593 Status
= EFI_OUT_OF_RESOURCES
;
1598 // Fill in the MemorySpaceMap
1600 Descriptor
= *MemorySpaceMap
;
1601 Link
= mGcdMemorySpaceMap
.ForwardLink
;
1602 while (Link
!= &mGcdMemorySpaceMap
) {
1603 Entry
= CR (Link
, EFI_GCD_MAP_ENTRY
, Link
, EFI_GCD_MAP_SIGNATURE
);
1604 BuildMemoryDescriptor (Descriptor
, Entry
);
1606 Link
= Link
->ForwardLink
;
1608 Status
= EFI_SUCCESS
;
1611 CoreReleaseGcdMemoryLock ();
1617 Adds reserved I/O or I/O resources to the global coherency domain of the processor.
1619 @param GcdIoType IO type of the segment.
1620 @param BaseAddress Base address of the segment.
1621 @param Length Length of the segment.
1623 @retval EFI_SUCCESS Merged this segment into GCD map.
1624 @retval EFI_INVALID_PARAMETER Parameter not valid
1630 IN EFI_GCD_IO_TYPE GcdIoType
,
1631 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
1635 DEBUG ((DEBUG_GCD
, "GCD:AddIoSpace(Base=%016lx,Length=%016lx)\n", BaseAddress
, Length
));
1636 DEBUG ((DEBUG_GCD
, " GcdIoType = %a\n", mGcdIoTypeNames
[MIN (GcdIoType
, EfiGcdIoTypeMaximum
)]));
1639 // Make sure parameters are valid
1641 if (GcdIoType
<= EfiGcdIoTypeNonExistent
|| GcdIoType
>= EfiGcdIoTypeMaximum
) {
1642 return EFI_INVALID_PARAMETER
;
1644 return CoreConvertSpace (GCD_ADD_IO_OPERATION
, (EFI_GCD_MEMORY_TYPE
) 0, GcdIoType
, BaseAddress
, Length
, 0, 0);
1649 Allocates nonexistent I/O, reserved I/O, or I/O resources from the global coherency
1650 domain of the processor.
1652 @param GcdAllocateType The type of allocate operation
1653 @param GcdIoType The desired IO type
1654 @param Alignment Align with 2^Alignment
1655 @param Length Length to allocate
1656 @param BaseAddress Base address to allocate
1657 @param ImageHandle The image handle consume the allocated space.
1658 @param DeviceHandle The device handle consume the allocated space.
1660 @retval EFI_INVALID_PARAMETER Invalid parameter.
1661 @retval EFI_NOT_FOUND No descriptor contains the desired space.
1662 @retval EFI_SUCCESS IO space successfully allocated.
1667 CoreAllocateIoSpace (
1668 IN EFI_GCD_ALLOCATE_TYPE GcdAllocateType
,
1669 IN EFI_GCD_IO_TYPE GcdIoType
,
1672 IN OUT EFI_PHYSICAL_ADDRESS
*BaseAddress
,
1673 IN EFI_HANDLE ImageHandle
,
1674 IN EFI_HANDLE DeviceHandle OPTIONAL
1677 DEBUG ((DEBUG_GCD
, "GCD:AllocateIoSpace(Base=%016lx,Length=%016lx)\n", *BaseAddress
, Length
));
1678 DEBUG ((DEBUG_GCD
, " GcdAllocateType = %a\n", mGcdAllocationTypeNames
[MIN (GcdAllocateType
, EfiGcdMaxAllocateType
)]));
1679 DEBUG ((DEBUG_GCD
, " GcdMemoryType = %a\n", mGcdIoTypeNames
[MIN (GcdIoType
, EfiGcdMemoryTypeMaximum
)]));
1680 DEBUG ((DEBUG_GCD
, " Alignment = %016lx\n", LShiftU64 (1, Alignment
)));
1681 DEBUG ((DEBUG_GCD
, " ImageHandle = %p\n", ImageHandle
));
1682 DEBUG ((DEBUG_GCD
, " DeviceHandle = %p\n", DeviceHandle
));
1684 return CoreAllocateSpace (
1685 GCD_ALLOCATE_IO_OPERATION
,
1687 (EFI_GCD_MEMORY_TYPE
) 0,
1699 Frees nonexistent I/O, reserved I/O, or I/O resources from the global coherency
1700 domain of the processor.
1702 @param BaseAddress Base address of the segment.
1703 @param Length Length of the segment.
1705 @retval EFI_SUCCESS Space successfully freed.
1711 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
1715 DEBUG ((DEBUG_GCD
, "GCD:FreeIoSpace(Base=%016lx,Length=%016lx)\n", BaseAddress
, Length
));
1717 return CoreConvertSpace (GCD_FREE_IO_OPERATION
, (EFI_GCD_MEMORY_TYPE
) 0, (EFI_GCD_IO_TYPE
) 0, BaseAddress
, Length
, 0, 0);
1722 Removes reserved I/O or I/O resources from the global coherency domain of the
1725 @param BaseAddress Base address of the segment.
1726 @param Length Length of the segment.
1728 @retval EFI_SUCCESS Successfully removed a segment of IO space.
1734 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
1738 DEBUG ((DEBUG_GCD
, "GCD:RemoveIoSpace(Base=%016lx,Length=%016lx)\n", BaseAddress
, Length
));
1740 return CoreConvertSpace (GCD_REMOVE_IO_OPERATION
, (EFI_GCD_MEMORY_TYPE
) 0, (EFI_GCD_IO_TYPE
) 0, BaseAddress
, Length
, 0, 0);
1745 Build a IO descriptor according to an entry.
1747 @param Descriptor The descriptor to be built
1748 @param Entry According to this entry
1753 IN EFI_GCD_IO_SPACE_DESCRIPTOR
*Descriptor
,
1754 IN EFI_GCD_MAP_ENTRY
*Entry
1757 Descriptor
->BaseAddress
= Entry
->BaseAddress
;
1758 Descriptor
->Length
= Entry
->EndAddress
- Entry
->BaseAddress
+ 1;
1759 Descriptor
->GcdIoType
= Entry
->GcdIoType
;
1760 Descriptor
->ImageHandle
= Entry
->ImageHandle
;
1761 Descriptor
->DeviceHandle
= Entry
->DeviceHandle
;
1766 Retrieves the descriptor for an I/O region containing a specified address.
1768 @param BaseAddress Specified start address
1769 @param Descriptor Specified length
1771 @retval EFI_INVALID_PARAMETER Descriptor is NULL.
1772 @retval EFI_SUCCESS Successfully get the IO space descriptor.
1777 CoreGetIoSpaceDescriptor (
1778 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
1779 OUT EFI_GCD_IO_SPACE_DESCRIPTOR
*Descriptor
1783 LIST_ENTRY
*StartLink
;
1784 LIST_ENTRY
*EndLink
;
1785 EFI_GCD_MAP_ENTRY
*Entry
;
1788 // Make sure parameters are valid
1790 if (Descriptor
== NULL
) {
1791 return EFI_INVALID_PARAMETER
;
1794 CoreAcquireGcdIoLock ();
1797 // Search for the list of descriptors that contain BaseAddress
1799 Status
= CoreSearchGcdMapEntry (BaseAddress
, 1, &StartLink
, &EndLink
, &mGcdIoSpaceMap
);
1800 if (EFI_ERROR (Status
)) {
1801 Status
= EFI_NOT_FOUND
;
1803 ASSERT (StartLink
!= NULL
&& EndLink
!= NULL
);
1805 // Copy the contents of the found descriptor into Descriptor
1807 Entry
= CR (StartLink
, EFI_GCD_MAP_ENTRY
, Link
, EFI_GCD_MAP_SIGNATURE
);
1808 BuildIoDescriptor (Descriptor
, Entry
);
1811 CoreReleaseGcdIoLock ();
1818 Returns a map of the I/O resources in the global coherency domain of the processor.
1820 @param NumberOfDescriptors Number of descriptors.
1821 @param IoSpaceMap Descriptor array
1823 @retval EFI_INVALID_PARAMETER Invalid parameter
1824 @retval EFI_OUT_OF_RESOURCES No enough buffer to allocate
1825 @retval EFI_SUCCESS Successfully get IO space map.
1831 OUT UINTN
*NumberOfDescriptors
,
1832 OUT EFI_GCD_IO_SPACE_DESCRIPTOR
**IoSpaceMap
1837 EFI_GCD_MAP_ENTRY
*Entry
;
1838 EFI_GCD_IO_SPACE_DESCRIPTOR
*Descriptor
;
1841 // Make sure parameters are valid
1843 if (NumberOfDescriptors
== NULL
) {
1844 return EFI_INVALID_PARAMETER
;
1846 if (IoSpaceMap
== NULL
) {
1847 return EFI_INVALID_PARAMETER
;
1850 CoreAcquireGcdIoLock ();
1853 // Count the number of descriptors
1855 *NumberOfDescriptors
= CoreCountGcdMapEntry (&mGcdIoSpaceMap
);
1858 // Allocate the IoSpaceMap
1860 *IoSpaceMap
= AllocatePool (*NumberOfDescriptors
* sizeof (EFI_GCD_IO_SPACE_DESCRIPTOR
));
1861 if (*IoSpaceMap
== NULL
) {
1862 Status
= EFI_OUT_OF_RESOURCES
;
1867 // Fill in the IoSpaceMap
1869 Descriptor
= *IoSpaceMap
;
1870 Link
= mGcdIoSpaceMap
.ForwardLink
;
1871 while (Link
!= &mGcdIoSpaceMap
) {
1872 Entry
= CR (Link
, EFI_GCD_MAP_ENTRY
, Link
, EFI_GCD_MAP_SIGNATURE
);
1873 BuildIoDescriptor (Descriptor
, Entry
);
1875 Link
= Link
->ForwardLink
;
1877 Status
= EFI_SUCCESS
;
1880 CoreReleaseGcdIoLock ();
1885 Converts a Resource Descriptor HOB attributes mask to an EFI Memory Descriptor
1888 @param GcdMemoryType Type of resource in the GCD memory map.
1889 @param Attributes The attribute mask in the Resource Descriptor
1892 @return The capabilities mask for an EFI Memory Descriptor.
1896 CoreConvertResourceDescriptorHobAttributesToCapabilities (
1897 EFI_GCD_MEMORY_TYPE GcdMemoryType
,
1901 UINT64 Capabilities
;
1902 GCD_ATTRIBUTE_CONVERSION_ENTRY
*Conversion
;
1905 // Convert the Resource HOB Attributes to an EFI Memory Capabilities mask
1907 for (Capabilities
= 0, Conversion
= mAttributeConversionTable
; Conversion
->Attribute
!= 0; Conversion
++) {
1908 if (Conversion
->Memory
|| (GcdMemoryType
!= EfiGcdMemoryTypeSystemMemory
)) {
1909 if (Attributes
& Conversion
->Attribute
) {
1910 Capabilities
|= Conversion
->Capability
;
1915 return Capabilities
;
1920 External function. Initializes memory services based on the memory
1921 descriptor HOBs. This function is responsible for priming the memory
1922 map, so memory allocations and resource allocations can be made.
1923 The first part of this function can not depend on any memory services
1924 until at least one memory descriptor is provided to the memory services.
1926 @param HobStart The start address of the HOB.
1927 @param MemoryBaseAddress Start address of memory region found to init DXE
1929 @param MemoryLength Length of memory region found to init DXE core.
1931 @retval EFI_SUCCESS Memory services successfully initialized.
1935 CoreInitializeMemoryServices (
1937 OUT EFI_PHYSICAL_ADDRESS
*MemoryBaseAddress
,
1938 OUT UINT64
*MemoryLength
1941 EFI_PEI_HOB_POINTERS Hob
;
1942 EFI_MEMORY_TYPE_INFORMATION
*EfiMemoryTypeInformation
;
1945 EFI_HOB_HANDOFF_INFO_TABLE
*PhitHob
;
1946 EFI_HOB_RESOURCE_DESCRIPTOR
*ResourceHob
;
1947 EFI_HOB_RESOURCE_DESCRIPTOR
*PhitResourceHob
;
1948 EFI_PHYSICAL_ADDRESS BaseAddress
;
1951 UINT64 Capabilities
;
1952 EFI_PHYSICAL_ADDRESS MaxMemoryBaseAddress
;
1953 UINT64 MaxMemoryLength
;
1954 UINT64 MaxMemoryAttributes
;
1955 EFI_PHYSICAL_ADDRESS MaxAddress
;
1956 EFI_PHYSICAL_ADDRESS HighAddress
;
1957 EFI_HOB_RESOURCE_DESCRIPTOR
*MaxResourceHob
;
1958 EFI_HOB_GUID_TYPE
*GuidHob
;
1959 UINT32 ReservedCodePageNumber
;
1962 // Point at the first HOB. This must be the PHIT HOB.
1964 Hob
.Raw
= *HobStart
;
1965 ASSERT (GET_HOB_TYPE (Hob
) == EFI_HOB_TYPE_HANDOFF
);
1968 // Initialize the spin locks and maps in the memory services.
1969 // Also fill in the memory services into the EFI Boot Services Table
1971 CoreInitializePool ();
1974 // Initialize Local Variables
1976 PhitResourceHob
= NULL
;
1977 MaxResourceHob
= NULL
;
1982 MaxMemoryBaseAddress
= 0;
1983 MaxMemoryLength
= 0;
1984 MaxMemoryAttributes
= 0;
1987 // Cache the PHIT HOB for later use
1989 PhitHob
= Hob
.HandoffInformationTable
;
1991 if (PcdGet64(PcdLoadModuleAtFixAddressEnable
) != 0) {
1992 ReservedCodePageNumber
= PcdGet32(PcdLoadFixAddressRuntimeCodePageNumber
);
1993 ReservedCodePageNumber
+= PcdGet32(PcdLoadFixAddressBootTimeCodePageNumber
);
1996 // cache the Top address for loading modules at Fixed Address
1998 gLoadModuleAtFixAddressConfigurationTable
.DxeCodeTopAddress
= PhitHob
->EfiMemoryTop
1999 + EFI_PAGES_TO_SIZE(ReservedCodePageNumber
);
2002 // See if a Memory Type Information HOB is available
2004 GuidHob
= GetFirstGuidHob (&gEfiMemoryTypeInformationGuid
);
2005 if (GuidHob
!= NULL
) {
2006 EfiMemoryTypeInformation
= GET_GUID_HOB_DATA (GuidHob
);
2007 DataSize
= GET_GUID_HOB_DATA_SIZE (GuidHob
);
2008 if (EfiMemoryTypeInformation
!= NULL
&& DataSize
> 0 && DataSize
<= (EfiMaxMemoryType
+ 1) * sizeof (EFI_MEMORY_TYPE_INFORMATION
)) {
2009 CopyMem (&gMemoryTypeInformation
, EfiMemoryTypeInformation
, DataSize
);
2014 // Find the Resource Descriptor HOB that contains range FreeMemoryBaseAddress..FreeMemoryLength
2018 for (Hob
.Raw
= *HobStart
; !END_OF_HOB_LIST(Hob
); Hob
.Raw
= GET_NEXT_HOB(Hob
)) {
2020 if (GET_HOB_TYPE (Hob
) == EFI_HOB_TYPE_RESOURCE_DESCRIPTOR
) {
2022 ResourceHob
= Hob
.ResourceDescriptor
;
2024 if (ResourceHob
->ResourceType
== EFI_RESOURCE_SYSTEM_MEMORY
&&
2025 (ResourceHob
->ResourceAttribute
& MEMORY_ATTRIBUTE_MASK
) == TESTED_MEMORY_ATTRIBUTES
) {
2027 if (PhitHob
->EfiFreeMemoryBottom
>= ResourceHob
->PhysicalStart
&&
2028 PhitHob
->EfiFreeMemoryTop
<= (ResourceHob
->PhysicalStart
+ ResourceHob
->ResourceLength
) ) {
2031 // Cache the resource descriptor HOB for the memory region described by the PHIT HOB
2033 PhitResourceHob
= ResourceHob
;
2036 Attributes
= PhitResourceHob
->ResourceAttribute
;
2037 BaseAddress
= PageAlignAddress (PhitHob
->EfiMemoryTop
);
2038 Length
= PageAlignLength (ResourceHob
->PhysicalStart
+ ResourceHob
->ResourceLength
- BaseAddress
);
2039 if (Length
< MINIMUM_INITIAL_MEMORY_SIZE
) {
2040 BaseAddress
= PageAlignAddress (PhitHob
->EfiFreeMemoryBottom
);
2041 Length
= PageAlignLength (PhitHob
->EfiFreeMemoryTop
- BaseAddress
);
2042 if (Length
< MINIMUM_INITIAL_MEMORY_SIZE
) {
2043 BaseAddress
= PageAlignAddress (ResourceHob
->PhysicalStart
);
2044 Length
= PageAlignLength ((UINT64
)((UINTN
)*HobStart
- BaseAddress
));
2054 // Assert if a resource descriptor HOB for the memory region described by the PHIT was not found
2059 // Search all the resource descriptor HOBs from the highest possible addresses down for a memory
2060 // region that is big enough to initialize the DXE core. Always skip the PHIT Resource HOB.
2061 // The max address must be within the physically addressible range for the processor.
2063 MaxMemoryLength
= 0;
2064 MaxAddress
= MAX_ADDRESS
;
2069 // Search for a tested memory region that is below MaxAddress
2071 for (Hob
.Raw
= *HobStart
; !END_OF_HOB_LIST(Hob
); Hob
.Raw
= GET_NEXT_HOB(Hob
)) {
2074 // See if this is a resource descriptor HOB that does not contain the PHIT.
2076 if (Hob
.ResourceDescriptor
!= PhitResourceHob
&& GET_HOB_TYPE (Hob
) == EFI_HOB_TYPE_RESOURCE_DESCRIPTOR
) {
2078 ResourceHob
= Hob
.ResourceDescriptor
;
2080 // See if this resource descrior HOB describes tested system memory below MaxAddress
2082 if (ResourceHob
->ResourceType
== EFI_RESOURCE_SYSTEM_MEMORY
&&
2083 (ResourceHob
->ResourceAttribute
& MEMORY_ATTRIBUTE_MASK
) == TESTED_MEMORY_ATTRIBUTES
&&
2084 ResourceHob
->PhysicalStart
+ ResourceHob
->ResourceLength
<= MaxAddress
) {
2086 // See if this is the highest tested system memory region below MaxAddress
2088 if (ResourceHob
->PhysicalStart
> HighAddress
) {
2090 MaxResourceHob
= ResourceHob
;
2091 HighAddress
= MaxResourceHob
->PhysicalStart
;
2099 // Compute the size of the tested memory region below MaxAddrees
2101 MaxMemoryBaseAddress
= PageAlignAddress (MaxResourceHob
->PhysicalStart
);
2102 MaxMemoryLength
= PageAlignLength (MaxResourceHob
->PhysicalStart
+ MaxResourceHob
->ResourceLength
- MaxMemoryBaseAddress
);
2103 MaxMemoryAttributes
= MaxResourceHob
->ResourceAttribute
;
2105 MaxAddress
= ResourceHob
->PhysicalStart
;
2106 } while (Found
&& MaxMemoryLength
< MINIMUM_INITIAL_MEMORY_SIZE
);
2108 if ((Length
< MINIMUM_INITIAL_MEMORY_SIZE
) ||
2109 (MaxMemoryBaseAddress
> BaseAddress
&& MaxMemoryLength
>= MINIMUM_INITIAL_MEMORY_SIZE
)) {
2110 BaseAddress
= MaxMemoryBaseAddress
;
2111 Length
= MaxMemoryLength
;
2112 Attributes
= MaxMemoryAttributes
;
2116 // If no memory regions are found that are big enough to initialize the DXE core, then ASSERT().
2118 ASSERT (Length
>= MINIMUM_INITIAL_MEMORY_SIZE
);
2121 // Convert the Resource HOB Attributes to an EFI Memory Capabilities mask
2123 Capabilities
= CoreConvertResourceDescriptorHobAttributesToCapabilities (EfiGcdMemoryTypeSystemMemory
, Attributes
);
2126 // Declare the very first memory region, so the EFI Memory Services are available.
2128 CoreAddMemoryDescriptor (
2129 EfiConventionalMemory
,
2131 RShiftU64 (Length
, EFI_PAGE_SHIFT
),
2135 *MemoryBaseAddress
= BaseAddress
;
2136 *MemoryLength
= Length
;
2143 External function. Initializes the GCD and memory services based on the memory
2144 descriptor HOBs. This function is responsible for priming the GCD map and the
2145 memory map, so memory allocations and resource allocations can be made. The
2146 HobStart will be relocated to a pool buffer.
2148 @param HobStart The start address of the HOB
2149 @param MemoryBaseAddress Start address of memory region found to init DXE
2151 @param MemoryLength Length of memory region found to init DXE core.
2153 @retval EFI_SUCCESS GCD services successfully initialized.
2157 CoreInitializeGcdServices (
2158 IN OUT VOID
**HobStart
,
2159 IN EFI_PHYSICAL_ADDRESS MemoryBaseAddress
,
2160 IN UINT64 MemoryLength
2163 EFI_PEI_HOB_POINTERS Hob
;
2165 EFI_HOB_HANDOFF_INFO_TABLE
*PhitHob
;
2166 UINT8 SizeOfMemorySpace
;
2167 UINT8 SizeOfIoSpace
;
2168 EFI_HOB_RESOURCE_DESCRIPTOR
*ResourceHob
;
2169 EFI_PHYSICAL_ADDRESS BaseAddress
;
2172 EFI_GCD_MAP_ENTRY
*Entry
;
2173 EFI_GCD_MEMORY_TYPE GcdMemoryType
;
2174 EFI_GCD_IO_TYPE GcdIoType
;
2175 EFI_GCD_MEMORY_SPACE_DESCRIPTOR Descriptor
;
2176 EFI_HOB_MEMORY_ALLOCATION
*MemoryHob
;
2177 EFI_HOB_FIRMWARE_VOLUME
*FirmwareVolumeHob
;
2178 UINTN NumberOfDescriptors
;
2179 EFI_GCD_MEMORY_SPACE_DESCRIPTOR
*MemorySpaceMap
;
2181 UINT64 Capabilities
;
2182 EFI_HOB_CPU
* CpuHob
;
2185 // Cache the PHIT HOB for later use
2187 PhitHob
= (EFI_HOB_HANDOFF_INFO_TABLE
*)(*HobStart
);
2190 // Get the number of address lines in the I/O and Memory space for the CPU
2192 CpuHob
= GetFirstHob (EFI_HOB_TYPE_CPU
);
2193 ASSERT (CpuHob
!= NULL
);
2194 SizeOfMemorySpace
= CpuHob
->SizeOfMemorySpace
;
2195 SizeOfIoSpace
= CpuHob
->SizeOfIoSpace
;
2198 // Initialize the GCD Memory Space Map
2200 Entry
= AllocateCopyPool (sizeof (EFI_GCD_MAP_ENTRY
), &mGcdMemorySpaceMapEntryTemplate
);
2201 ASSERT (Entry
!= NULL
);
2203 Entry
->EndAddress
= LShiftU64 (1, SizeOfMemorySpace
) - 1;
2205 InsertHeadList (&mGcdMemorySpaceMap
, &Entry
->Link
);
2207 DEBUG_CODE_BEGIN ();
2208 DEBUG ((DEBUG_GCD
, "GCD:Initial GCD Memory Space Map\n"));
2209 CoreDumpGcdMemorySpaceMap ();
2213 // Initialize the GCD I/O Space Map
2215 Entry
= AllocateCopyPool (sizeof (EFI_GCD_MAP_ENTRY
), &mGcdIoSpaceMapEntryTemplate
);
2216 ASSERT (Entry
!= NULL
);
2218 Entry
->EndAddress
= LShiftU64 (1, SizeOfIoSpace
) - 1;
2220 InsertHeadList (&mGcdIoSpaceMap
, &Entry
->Link
);
2222 DEBUG_CODE_BEGIN ();
2223 DEBUG ((DEBUG_GCD
, "GCD:Initial GCD I/O Space Map\n"));
2224 CoreDumpGcdIoSpaceMap ();
2228 // Walk the HOB list and add all resource descriptors to the GCD
2230 for (Hob
.Raw
= *HobStart
; !END_OF_HOB_LIST(Hob
); Hob
.Raw
= GET_NEXT_HOB(Hob
)) {
2232 GcdMemoryType
= EfiGcdMemoryTypeNonExistent
;
2233 GcdIoType
= EfiGcdIoTypeNonExistent
;
2235 if (GET_HOB_TYPE (Hob
) == EFI_HOB_TYPE_RESOURCE_DESCRIPTOR
) {
2237 ResourceHob
= Hob
.ResourceDescriptor
;
2239 switch (ResourceHob
->ResourceType
) {
2240 case EFI_RESOURCE_SYSTEM_MEMORY
:
2241 if ((ResourceHob
->ResourceAttribute
& MEMORY_ATTRIBUTE_MASK
) == TESTED_MEMORY_ATTRIBUTES
) {
2242 GcdMemoryType
= EfiGcdMemoryTypeSystemMemory
;
2244 if ((ResourceHob
->ResourceAttribute
& MEMORY_ATTRIBUTE_MASK
) == INITIALIZED_MEMORY_ATTRIBUTES
) {
2245 GcdMemoryType
= EfiGcdMemoryTypeReserved
;
2247 if ((ResourceHob
->ResourceAttribute
& MEMORY_ATTRIBUTE_MASK
) == PRESENT_MEMORY_ATTRIBUTES
) {
2248 GcdMemoryType
= EfiGcdMemoryTypeReserved
;
2251 case EFI_RESOURCE_MEMORY_MAPPED_IO
:
2252 case EFI_RESOURCE_FIRMWARE_DEVICE
:
2253 GcdMemoryType
= EfiGcdMemoryTypeMemoryMappedIo
;
2255 case EFI_RESOURCE_MEMORY_MAPPED_IO_PORT
:
2256 case EFI_RESOURCE_MEMORY_RESERVED
:
2257 GcdMemoryType
= EfiGcdMemoryTypeReserved
;
2259 case EFI_RESOURCE_IO
:
2260 GcdIoType
= EfiGcdIoTypeIo
;
2262 case EFI_RESOURCE_IO_RESERVED
:
2263 GcdIoType
= EfiGcdIoTypeReserved
;
2267 if (GcdMemoryType
!= EfiGcdMemoryTypeNonExistent
) {
2269 // Convert the Resource HOB Attributes to an EFI Memory Capabilities mask
2271 Capabilities
= CoreConvertResourceDescriptorHobAttributesToCapabilities (
2273 ResourceHob
->ResourceAttribute
2276 Status
= CoreInternalAddMemorySpace (
2278 ResourceHob
->PhysicalStart
,
2279 ResourceHob
->ResourceLength
,
2284 if (GcdIoType
!= EfiGcdIoTypeNonExistent
) {
2285 Status
= CoreAddIoSpace (
2287 ResourceHob
->PhysicalStart
,
2288 ResourceHob
->ResourceLength
2295 // Allocate first memory region from the GCD by the DXE core
2297 Status
= CoreAllocateMemorySpace (
2298 EfiGcdAllocateAddress
,
2299 EfiGcdMemoryTypeSystemMemory
,
2303 gDxeCoreImageHandle
,
2308 // Walk the HOB list and allocate all memory space that is consumed by memory allocation HOBs,
2309 // and Firmware Volume HOBs. Also update the EFI Memory Map with the memory allocation HOBs.
2311 for (Hob
.Raw
= *HobStart
; !END_OF_HOB_LIST(Hob
); Hob
.Raw
= GET_NEXT_HOB(Hob
)) {
2312 if (GET_HOB_TYPE (Hob
) == EFI_HOB_TYPE_MEMORY_ALLOCATION
) {
2313 MemoryHob
= Hob
.MemoryAllocation
;
2314 BaseAddress
= MemoryHob
->AllocDescriptor
.MemoryBaseAddress
;
2315 Status
= CoreGetMemorySpaceDescriptor (BaseAddress
, &Descriptor
);
2316 if (!EFI_ERROR (Status
)) {
2317 Status
= CoreAllocateMemorySpace (
2318 EfiGcdAllocateAddress
,
2319 Descriptor
.GcdMemoryType
,
2321 MemoryHob
->AllocDescriptor
.MemoryLength
,
2323 gDxeCoreImageHandle
,
2326 if (!EFI_ERROR (Status
) && Descriptor
.GcdMemoryType
== EfiGcdMemoryTypeSystemMemory
) {
2327 CoreAddMemoryDescriptor (
2328 MemoryHob
->AllocDescriptor
.MemoryType
,
2329 MemoryHob
->AllocDescriptor
.MemoryBaseAddress
,
2330 RShiftU64 (MemoryHob
->AllocDescriptor
.MemoryLength
, EFI_PAGE_SHIFT
),
2331 Descriptor
.Capabilities
& (~EFI_MEMORY_RUNTIME
)
2337 if (GET_HOB_TYPE (Hob
) == EFI_HOB_TYPE_FV
) {
2338 FirmwareVolumeHob
= Hob
.FirmwareVolume
;
2339 BaseAddress
= FirmwareVolumeHob
->BaseAddress
;
2340 Status
= CoreAllocateMemorySpace (
2341 EfiGcdAllocateAddress
,
2342 EfiGcdMemoryTypeMemoryMappedIo
,
2344 FirmwareVolumeHob
->Length
,
2346 gDxeCoreImageHandle
,
2353 // Relocate HOB List to an allocated pool buffer.
2355 NewHobList
= AllocateCopyPool (
2356 (UINTN
)PhitHob
->EfiFreeMemoryBottom
- (UINTN
)(*HobStart
),
2359 ASSERT (NewHobList
!= NULL
);
2361 *HobStart
= NewHobList
;
2362 gHobList
= NewHobList
;
2365 // Add and allocate the remaining unallocated system memory to the memory services.
2367 Status
= CoreGetMemorySpaceMap (&NumberOfDescriptors
, &MemorySpaceMap
);
2368 ASSERT (Status
== EFI_SUCCESS
);
2370 for (Index
= 0; Index
< NumberOfDescriptors
; Index
++) {
2371 if (MemorySpaceMap
[Index
].GcdMemoryType
== EfiGcdMemoryTypeSystemMemory
) {
2372 if (MemorySpaceMap
[Index
].ImageHandle
== NULL
) {
2373 BaseAddress
= PageAlignAddress (MemorySpaceMap
[Index
].BaseAddress
);
2374 Length
= PageAlignLength (MemorySpaceMap
[Index
].BaseAddress
+ MemorySpaceMap
[Index
].Length
- BaseAddress
);
2375 if (Length
== 0 || MemorySpaceMap
[Index
].BaseAddress
+ MemorySpaceMap
[Index
].Length
< BaseAddress
) {
2378 CoreAddMemoryDescriptor (
2379 EfiConventionalMemory
,
2381 RShiftU64 (Length
, EFI_PAGE_SHIFT
),
2382 MemorySpaceMap
[Index
].Capabilities
& (~EFI_MEMORY_RUNTIME
)
2384 Status
= CoreAllocateMemorySpace (
2385 EfiGcdAllocateAddress
,
2386 EfiGcdMemoryTypeSystemMemory
,
2390 gDxeCoreImageHandle
,
2396 CoreFreePool (MemorySpaceMap
);