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.
135 @param InitialMap TRUE if the initial GCD Memory Map is being dumped. Otherwise, FALSE.
140 CoreDumpGcdMemorySpaceMap (
146 UINTN NumberOfDescriptors
;
147 EFI_GCD_MEMORY_SPACE_DESCRIPTOR
*MemorySpaceMap
;
150 Status
= CoreGetMemorySpaceMap (&NumberOfDescriptors
, &MemorySpaceMap
);
151 ASSERT_EFI_ERROR (Status
);
154 DEBUG ((DEBUG_GCD
, "GCD:Initial GCD Memory Space Map\n"));
156 DEBUG ((DEBUG_GCD
, "GCDMemType Range Capabilities Attributes \n"));
157 DEBUG ((DEBUG_GCD
, "========== ================================= ================ ================\n"));
158 for (Index
= 0; Index
< NumberOfDescriptors
; Index
++) {
159 DEBUG ((DEBUG_GCD
, "%a %016lx-%016lx %016lx %016lx%c\n",
160 mGcdMemoryTypeNames
[MIN (MemorySpaceMap
[Index
].GcdMemoryType
, EfiGcdMemoryTypeMaximum
)],
161 MemorySpaceMap
[Index
].BaseAddress
,
162 MemorySpaceMap
[Index
].BaseAddress
+ MemorySpaceMap
[Index
].Length
- 1,
163 MemorySpaceMap
[Index
].Capabilities
,
164 MemorySpaceMap
[Index
].Attributes
,
165 MemorySpaceMap
[Index
].ImageHandle
== NULL
? ' ' : '*'
168 DEBUG ((DEBUG_GCD
, "\n"));
169 FreePool (MemorySpaceMap
);
174 Dump the entire contents if the GCD I/O Space Map using DEBUG() macros when
175 PcdDebugPrintErrorLevel has the DEBUG_GCD bit set.
177 @param InitialMap TRUE if the initial GCD I/O Map is being dumped. Otherwise, FALSE.
182 CoreDumpGcdIoSpaceMap (
188 UINTN NumberOfDescriptors
;
189 EFI_GCD_IO_SPACE_DESCRIPTOR
*IoSpaceMap
;
192 Status
= CoreGetIoSpaceMap (&NumberOfDescriptors
, &IoSpaceMap
);
193 ASSERT_EFI_ERROR (Status
);
196 DEBUG ((DEBUG_GCD
, "GCD:Initial GCD I/O Space Map\n"));
199 DEBUG ((DEBUG_GCD
, "GCDIoType Range \n"));
200 DEBUG ((DEBUG_GCD
, "========== =================================\n"));
201 for (Index
= 0; Index
< NumberOfDescriptors
; Index
++) {
202 DEBUG ((DEBUG_GCD
, "%a %016lx-%016lx%c\n",
203 mGcdIoTypeNames
[MIN (IoSpaceMap
[Index
].GcdIoType
, EfiGcdIoTypeMaximum
)],
204 IoSpaceMap
[Index
].BaseAddress
,
205 IoSpaceMap
[Index
].BaseAddress
+ IoSpaceMap
[Index
].Length
- 1,
206 IoSpaceMap
[Index
].ImageHandle
== NULL
? ' ' : '*'
209 DEBUG ((DEBUG_GCD
, "\n"));
210 FreePool (IoSpaceMap
);
217 Acquire memory lock on mGcdMemorySpaceLock.
221 CoreAcquireGcdMemoryLock (
225 CoreAcquireLock (&mGcdMemorySpaceLock
);
231 Release memory lock on mGcdMemorySpaceLock.
235 CoreReleaseGcdMemoryLock (
239 CoreReleaseLock (&mGcdMemorySpaceLock
);
245 Acquire memory lock on mGcdIoSpaceLock.
249 CoreAcquireGcdIoLock (
253 CoreAcquireLock (&mGcdIoSpaceLock
);
258 Release memory lock on mGcdIoSpaceLock.
262 CoreReleaseGcdIoLock (
266 CoreReleaseLock (&mGcdIoSpaceLock
);
272 // GCD Initialization Worker Functions
275 Aligns a value to the specified boundary.
277 @param Value 64 bit value to align
278 @param Alignment Log base 2 of the boundary to align Value to
279 @param RoundUp TRUE if Value is to be rounded up to the nearest
280 aligned boundary. FALSE is Value is to be
281 rounded down to the nearest aligned boundary.
283 @return A 64 bit value is the aligned to the value nearest Value with an alignment by Alignment.
293 UINT64 AlignmentMask
;
295 AlignmentMask
= LShiftU64 (1, Alignment
) - 1;
297 Value
+= AlignmentMask
;
299 return Value
& (~AlignmentMask
);
304 Aligns address to the page boundary.
306 @param Value 64 bit address to align
308 @return A 64 bit value is the aligned to the value nearest Value with an alignment by Alignment.
316 return AlignValue (Value
, EFI_PAGE_SHIFT
, TRUE
);
321 Aligns length to the page boundary.
323 @param Value 64 bit length to align
325 @return A 64 bit value is the aligned to the value nearest Value with an alignment by Alignment.
333 return AlignValue (Value
, EFI_PAGE_SHIFT
, FALSE
);
337 // GCD Memory Space Worker Functions
341 Allocate pool for two entries.
343 @param TopEntry An entry of GCD map
344 @param BottomEntry An entry of GCD map
346 @retval EFI_OUT_OF_RESOURCES No enough buffer to be allocated.
347 @retval EFI_SUCCESS Both entries successfully allocated.
351 CoreAllocateGcdMapEntry (
352 IN OUT EFI_GCD_MAP_ENTRY
**TopEntry
,
353 IN OUT EFI_GCD_MAP_ENTRY
**BottomEntry
356 *TopEntry
= AllocateZeroPool (sizeof (EFI_GCD_MAP_ENTRY
));
357 if (*TopEntry
== NULL
) {
358 return EFI_OUT_OF_RESOURCES
;
361 *BottomEntry
= AllocateZeroPool (sizeof (EFI_GCD_MAP_ENTRY
));
362 if (*BottomEntry
== NULL
) {
363 CoreFreePool (*TopEntry
);
364 return EFI_OUT_OF_RESOURCES
;
372 Internal function. Inserts a new descriptor into a sorted list
374 @param Link The linked list to insert the range BaseAddress
376 @param Entry A pointer to the entry that is inserted
377 @param BaseAddress The base address of the new range
378 @param Length The length of the new range in bytes
379 @param TopEntry Top pad entry to insert if needed.
380 @param BottomEntry Bottom pad entry to insert if needed.
382 @retval EFI_SUCCESS The new range was inserted into the linked list
386 CoreInsertGcdMapEntry (
388 IN EFI_GCD_MAP_ENTRY
*Entry
,
389 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
391 IN EFI_GCD_MAP_ENTRY
*TopEntry
,
392 IN EFI_GCD_MAP_ENTRY
*BottomEntry
395 ASSERT (Length
!= 0);
397 if (BaseAddress
> Entry
->BaseAddress
) {
398 ASSERT (BottomEntry
->Signature
== 0);
400 CopyMem (BottomEntry
, Entry
, sizeof (EFI_GCD_MAP_ENTRY
));
401 Entry
->BaseAddress
= BaseAddress
;
402 BottomEntry
->EndAddress
= BaseAddress
- 1;
403 InsertTailList (Link
, &BottomEntry
->Link
);
406 if ((BaseAddress
+ Length
- 1) < Entry
->EndAddress
) {
407 ASSERT (TopEntry
->Signature
== 0);
409 CopyMem (TopEntry
, Entry
, sizeof (EFI_GCD_MAP_ENTRY
));
410 TopEntry
->BaseAddress
= BaseAddress
+ Length
;
411 Entry
->EndAddress
= BaseAddress
+ Length
- 1;
412 InsertHeadList (Link
, &TopEntry
->Link
);
420 Merge the Gcd region specified by Link and its adjacent entry.
422 @param Link Specify the entry to be merged (with its
424 @param Forward Direction (forward or backward).
427 @retval EFI_SUCCESS Successfully returned.
428 @retval EFI_UNSUPPORTED These adjacent regions could not merge.
432 CoreMergeGcdMapEntry (
438 LIST_ENTRY
*AdjacentLink
;
439 EFI_GCD_MAP_ENTRY
*Entry
;
440 EFI_GCD_MAP_ENTRY
*AdjacentEntry
;
443 // Get adjacent entry
446 AdjacentLink
= Link
->ForwardLink
;
448 AdjacentLink
= Link
->BackLink
;
452 // If AdjacentLink is the head of the list, then no merge can be performed
454 if (AdjacentLink
== Map
) {
458 Entry
= CR (Link
, EFI_GCD_MAP_ENTRY
, Link
, EFI_GCD_MAP_SIGNATURE
);
459 AdjacentEntry
= CR (AdjacentLink
, EFI_GCD_MAP_ENTRY
, Link
, EFI_GCD_MAP_SIGNATURE
);
461 if (Entry
->Capabilities
!= AdjacentEntry
->Capabilities
) {
462 return EFI_UNSUPPORTED
;
464 if (Entry
->Attributes
!= AdjacentEntry
->Attributes
) {
465 return EFI_UNSUPPORTED
;
467 if (Entry
->GcdMemoryType
!= AdjacentEntry
->GcdMemoryType
) {
468 return EFI_UNSUPPORTED
;
470 if (Entry
->GcdIoType
!= AdjacentEntry
->GcdIoType
) {
471 return EFI_UNSUPPORTED
;
473 if (Entry
->ImageHandle
!= AdjacentEntry
->ImageHandle
) {
474 return EFI_UNSUPPORTED
;
476 if (Entry
->DeviceHandle
!= AdjacentEntry
->DeviceHandle
) {
477 return EFI_UNSUPPORTED
;
481 Entry
->EndAddress
= AdjacentEntry
->EndAddress
;
483 Entry
->BaseAddress
= AdjacentEntry
->BaseAddress
;
485 RemoveEntryList (AdjacentLink
);
486 CoreFreePool (AdjacentEntry
);
493 Merge adjacent entries on total chain.
495 @param TopEntry Top entry of GCD map.
496 @param BottomEntry Bottom entry of GCD map.
497 @param StartLink Start link of the list for this loop.
498 @param EndLink End link of the list for this loop.
501 @retval EFI_SUCCESS GCD map successfully cleaned up.
505 CoreCleanupGcdMapEntry (
506 IN EFI_GCD_MAP_ENTRY
*TopEntry
,
507 IN EFI_GCD_MAP_ENTRY
*BottomEntry
,
508 IN LIST_ENTRY
*StartLink
,
509 IN LIST_ENTRY
*EndLink
,
515 if (TopEntry
->Signature
== 0) {
516 CoreFreePool (TopEntry
);
518 if (BottomEntry
->Signature
== 0) {
519 CoreFreePool (BottomEntry
);
523 while (Link
!= EndLink
->ForwardLink
) {
524 CoreMergeGcdMapEntry (Link
, FALSE
, Map
);
525 Link
= Link
->ForwardLink
;
527 CoreMergeGcdMapEntry (EndLink
, TRUE
, Map
);
534 Search a segment of memory space in GCD map. The result is a range of GCD entry list.
536 @param BaseAddress The start address of the segment.
537 @param Length The length of the segment.
538 @param StartLink The first GCD entry involves this segment of
540 @param EndLink The first GCD entry involves this segment of
542 @param Map Points to the start entry to search.
544 @retval EFI_SUCCESS Successfully found the entry.
545 @retval EFI_NOT_FOUND Not found.
549 CoreSearchGcdMapEntry (
550 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
552 OUT LIST_ENTRY
**StartLink
,
553 OUT LIST_ENTRY
**EndLink
,
558 EFI_GCD_MAP_ENTRY
*Entry
;
560 ASSERT (Length
!= 0);
565 Link
= Map
->ForwardLink
;
566 while (Link
!= Map
) {
567 Entry
= CR (Link
, EFI_GCD_MAP_ENTRY
, Link
, EFI_GCD_MAP_SIGNATURE
);
568 if (BaseAddress
>= Entry
->BaseAddress
&& BaseAddress
<= Entry
->EndAddress
) {
571 if (*StartLink
!= NULL
) {
572 if ((BaseAddress
+ Length
- 1) >= Entry
->BaseAddress
&&
573 (BaseAddress
+ Length
- 1) <= Entry
->EndAddress
) {
578 Link
= Link
->ForwardLink
;
581 return EFI_NOT_FOUND
;
586 Count the amount of GCD map entries.
588 @param Map Points to the start entry to do the count loop.
594 CoreCountGcdMapEntry (
602 Link
= Map
->ForwardLink
;
603 while (Link
!= Map
) {
605 Link
= Link
->ForwardLink
;
614 Return the memory attribute specified by Attributes
616 @param Attributes A num with some attribute bits on.
618 @return The enum value of memory attribute.
622 ConverToCpuArchAttributes (
626 if ( (Attributes
& EFI_MEMORY_UC
) == EFI_MEMORY_UC
) {
627 return EFI_MEMORY_UC
;
630 if ( (Attributes
& EFI_MEMORY_WC
) == EFI_MEMORY_WC
) {
631 return EFI_MEMORY_WC
;
634 if ( (Attributes
& EFI_MEMORY_WT
) == EFI_MEMORY_WT
) {
635 return EFI_MEMORY_WT
;
638 if ( (Attributes
& EFI_MEMORY_WB
) == EFI_MEMORY_WB
) {
639 return EFI_MEMORY_WB
;
642 if ( (Attributes
& EFI_MEMORY_WP
) == EFI_MEMORY_WP
) {
643 return EFI_MEMORY_WP
;
646 return INVALID_CPU_ARCH_ATTRIBUTES
;
652 Do operation on a segment of memory space specified (add, free, remove, change attribute ...).
654 @param Operation The type of the operation
655 @param GcdMemoryType Additional information for the operation
656 @param GcdIoType Additional information for the operation
657 @param BaseAddress Start address of the segment
658 @param Length length of the segment
659 @param Capabilities The alterable attributes of a newly added entry
660 @param Attributes The attributes needs to be set
662 @retval EFI_INVALID_PARAMETER Length is 0 or address (length) not aligned when
664 @retval EFI_SUCCESS Action successfully done.
665 @retval EFI_UNSUPPORTED Could not find the proper descriptor on this
666 segment or set an upsupported attribute.
667 @retval EFI_ACCESS_DENIED Operate on an space non-exist or is used for an
669 @retval EFI_NOT_FOUND Free a non-using space or remove a non-exist
671 @retval EFI_OUT_OF_RESOURCES No buffer could be allocated.
677 IN EFI_GCD_MEMORY_TYPE GcdMemoryType
,
678 IN EFI_GCD_IO_TYPE GcdIoType
,
679 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
681 IN UINT64 Capabilities
,
688 EFI_GCD_MAP_ENTRY
*Entry
;
689 EFI_GCD_MAP_ENTRY
*TopEntry
;
690 EFI_GCD_MAP_ENTRY
*BottomEntry
;
691 LIST_ENTRY
*StartLink
;
693 UINT64 CpuArchAttributes
;
696 DEBUG ((DEBUG_GCD
, " Status = %r\n", EFI_INVALID_PARAMETER
));
697 return EFI_INVALID_PARAMETER
;
701 if ((Operation
& GCD_MEMORY_SPACE_OPERATION
) != 0) {
702 CoreAcquireGcdMemoryLock ();
703 Map
= &mGcdMemorySpaceMap
;
704 } else if ((Operation
& GCD_IO_SPACE_OPERATION
) != 0) {
705 CoreAcquireGcdIoLock ();
706 Map
= &mGcdIoSpaceMap
;
712 // Search for the list of descriptors that cover the range BaseAddress to BaseAddress+Length
714 Status
= CoreSearchGcdMapEntry (BaseAddress
, Length
, &StartLink
, &EndLink
, Map
);
715 if (EFI_ERROR (Status
)) {
716 Status
= EFI_UNSUPPORTED
;
720 ASSERT (StartLink
!= NULL
&& EndLink
!= NULL
);
723 // Verify that the list of descriptors are unallocated non-existent memory.
726 while (Link
!= EndLink
->ForwardLink
) {
727 Entry
= CR (Link
, EFI_GCD_MAP_ENTRY
, Link
, EFI_GCD_MAP_SIGNATURE
);
732 case GCD_ADD_MEMORY_OPERATION
:
733 if (Entry
->GcdMemoryType
!= EfiGcdMemoryTypeNonExistent
||
734 Entry
->ImageHandle
!= NULL
) {
735 Status
= EFI_ACCESS_DENIED
;
739 case GCD_ADD_IO_OPERATION
:
740 if (Entry
->GcdIoType
!= EfiGcdIoTypeNonExistent
||
741 Entry
->ImageHandle
!= NULL
) {
742 Status
= EFI_ACCESS_DENIED
;
749 case GCD_FREE_MEMORY_OPERATION
:
750 case GCD_FREE_IO_OPERATION
:
751 if (Entry
->ImageHandle
== NULL
) {
752 Status
= EFI_NOT_FOUND
;
759 case GCD_REMOVE_MEMORY_OPERATION
:
760 if (Entry
->GcdMemoryType
== EfiGcdMemoryTypeNonExistent
) {
761 Status
= EFI_NOT_FOUND
;
764 if (Entry
->ImageHandle
!= NULL
) {
765 Status
= EFI_ACCESS_DENIED
;
769 case GCD_REMOVE_IO_OPERATION
:
770 if (Entry
->GcdIoType
== EfiGcdIoTypeNonExistent
) {
771 Status
= EFI_NOT_FOUND
;
774 if (Entry
->ImageHandle
!= NULL
) {
775 Status
= EFI_ACCESS_DENIED
;
780 // Set attribute operations
782 case GCD_SET_ATTRIBUTES_MEMORY_OPERATION
:
783 if ((Attributes
& EFI_MEMORY_RUNTIME
) != 0) {
784 if ((BaseAddress
& EFI_PAGE_MASK
) != 0 || (Length
& EFI_PAGE_MASK
) != 0) {
785 Status
= EFI_INVALID_PARAMETER
;
789 if ((Entry
->Capabilities
& Attributes
) != Attributes
) {
790 Status
= EFI_UNSUPPORTED
;
795 Link
= Link
->ForwardLink
;
799 // Allocate work space to perform this operation
801 Status
= CoreAllocateGcdMapEntry (&TopEntry
, &BottomEntry
);
802 if (EFI_ERROR (Status
)) {
803 Status
= EFI_OUT_OF_RESOURCES
;
806 ASSERT (TopEntry
!= NULL
&& BottomEntry
!= NULL
);
808 if (Operation
== GCD_SET_ATTRIBUTES_MEMORY_OPERATION
) {
810 // Call CPU Arch Protocol to attempt to set attributes on the range
812 CpuArchAttributes
= ConverToCpuArchAttributes (Attributes
);
813 if (CpuArchAttributes
!= INVALID_CPU_ARCH_ATTRIBUTES
) {
815 Status
= gCpu
->SetMemoryAttributes (
821 if (EFI_ERROR (Status
)) {
829 // Convert/Insert the list of descriptors from StartLink to EndLink
832 while (Link
!= EndLink
->ForwardLink
) {
833 Entry
= CR (Link
, EFI_GCD_MAP_ENTRY
, Link
, EFI_GCD_MAP_SIGNATURE
);
834 CoreInsertGcdMapEntry (Link
, Entry
, BaseAddress
, Length
, TopEntry
, BottomEntry
);
839 case GCD_ADD_MEMORY_OPERATION
:
840 Entry
->GcdMemoryType
= GcdMemoryType
;
841 if (GcdMemoryType
== EfiGcdMemoryTypeMemoryMappedIo
) {
842 Entry
->Capabilities
= Capabilities
| EFI_MEMORY_RUNTIME
| EFI_MEMORY_PORT_IO
;
844 Entry
->Capabilities
= Capabilities
| EFI_MEMORY_RUNTIME
;
847 case GCD_ADD_IO_OPERATION
:
848 Entry
->GcdIoType
= GcdIoType
;
853 case GCD_FREE_MEMORY_OPERATION
:
854 case GCD_FREE_IO_OPERATION
:
855 Entry
->ImageHandle
= NULL
;
856 Entry
->DeviceHandle
= NULL
;
861 case GCD_REMOVE_MEMORY_OPERATION
:
862 Entry
->GcdMemoryType
= EfiGcdMemoryTypeNonExistent
;
863 Entry
->Capabilities
= 0;
865 case GCD_REMOVE_IO_OPERATION
:
866 Entry
->GcdIoType
= EfiGcdIoTypeNonExistent
;
869 // Set attribute operations
871 case GCD_SET_ATTRIBUTES_MEMORY_OPERATION
:
872 Entry
->Attributes
= Attributes
;
875 Link
= Link
->ForwardLink
;
881 Status
= CoreCleanupGcdMapEntry (TopEntry
, BottomEntry
, StartLink
, EndLink
, Map
);
884 DEBUG ((DEBUG_GCD
, " Status = %r\n", Status
));
886 if ((Operation
& GCD_MEMORY_SPACE_OPERATION
) != 0) {
887 CoreReleaseGcdMemoryLock ();
888 CoreDumpGcdMemorySpaceMap (FALSE
);
890 if ((Operation
& GCD_IO_SPACE_OPERATION
) != 0) {
891 CoreReleaseGcdIoLock ();
892 CoreDumpGcdIoSpaceMap (FALSE
);
900 Check whether an entry could be used to allocate space.
902 @param Operation Allocate memory or IO
903 @param Entry The entry to be tested
904 @param GcdMemoryType The desired memory type
905 @param GcdIoType The desired IO type
907 @retval EFI_NOT_FOUND The memory type does not match or there's an
908 image handle on the entry.
909 @retval EFI_UNSUPPORTED The operation unsupported.
910 @retval EFI_SUCCESS It's ok for this entry to be used to allocate
915 CoreAllocateSpaceCheckEntry (
917 IN EFI_GCD_MAP_ENTRY
*Entry
,
918 IN EFI_GCD_MEMORY_TYPE GcdMemoryType
,
919 IN EFI_GCD_IO_TYPE GcdIoType
922 if (Entry
->ImageHandle
!= NULL
) {
923 return EFI_NOT_FOUND
;
926 case GCD_ALLOCATE_MEMORY_OPERATION
:
927 if (Entry
->GcdMemoryType
!= GcdMemoryType
) {
928 return EFI_NOT_FOUND
;
931 case GCD_ALLOCATE_IO_OPERATION
:
932 if (Entry
->GcdIoType
!= GcdIoType
) {
933 return EFI_NOT_FOUND
;
937 return EFI_UNSUPPORTED
;
944 Allocate space on specified address and length.
946 @param Operation The type of operation (memory or IO)
947 @param GcdAllocateType The type of allocate operation
948 @param GcdMemoryType The desired memory type
949 @param GcdIoType The desired IO type
950 @param Alignment Align with 2^Alignment
951 @param Length Length to allocate
952 @param BaseAddress Base address to allocate
953 @param ImageHandle The image handle consume the allocated space.
954 @param DeviceHandle The device handle consume the allocated space.
956 @retval EFI_INVALID_PARAMETER Invalid parameter.
957 @retval EFI_NOT_FOUND No descriptor for the desired space exists.
958 @retval EFI_SUCCESS Space successfully allocated.
964 IN EFI_GCD_ALLOCATE_TYPE GcdAllocateType
,
965 IN EFI_GCD_MEMORY_TYPE GcdMemoryType
,
966 IN EFI_GCD_IO_TYPE GcdIoType
,
969 IN OUT EFI_PHYSICAL_ADDRESS
*BaseAddress
,
970 IN EFI_HANDLE ImageHandle
,
971 IN EFI_HANDLE DeviceHandle OPTIONAL
975 EFI_PHYSICAL_ADDRESS AlignmentMask
;
976 EFI_PHYSICAL_ADDRESS MaxAddress
;
980 EFI_GCD_MAP_ENTRY
*Entry
;
981 EFI_GCD_MAP_ENTRY
*TopEntry
;
982 EFI_GCD_MAP_ENTRY
*BottomEntry
;
983 LIST_ENTRY
*StartLink
;
988 // Make sure parameters are valid
990 if (GcdAllocateType
< 0 || GcdAllocateType
>= EfiGcdMaxAllocateType
) {
991 DEBUG ((DEBUG_GCD
, " Status = %r\n", EFI_INVALID_PARAMETER
));
992 return EFI_INVALID_PARAMETER
;
994 if (GcdMemoryType
< 0 || GcdMemoryType
>= EfiGcdMemoryTypeMaximum
) {
995 DEBUG ((DEBUG_GCD
, " Status = %r\n", EFI_INVALID_PARAMETER
));
996 return EFI_INVALID_PARAMETER
;
998 if (GcdIoType
< 0 || GcdIoType
>= EfiGcdIoTypeMaximum
) {
999 DEBUG ((DEBUG_GCD
, " Status = %r\n", EFI_INVALID_PARAMETER
));
1000 return EFI_INVALID_PARAMETER
;
1002 if (BaseAddress
== NULL
) {
1003 DEBUG ((DEBUG_GCD
, " Status = %r\n", EFI_INVALID_PARAMETER
));
1004 return EFI_INVALID_PARAMETER
;
1006 if (ImageHandle
== NULL
) {
1007 DEBUG ((DEBUG_GCD
, " Status = %r\n", EFI_INVALID_PARAMETER
));
1008 return EFI_INVALID_PARAMETER
;
1010 if (Alignment
>= 64) {
1011 DEBUG ((DEBUG_GCD
, " Status = %r\n", EFI_NOT_FOUND
));
1012 return EFI_NOT_FOUND
;
1015 DEBUG ((DEBUG_GCD
, " Status = %r\n", EFI_INVALID_PARAMETER
));
1016 return EFI_INVALID_PARAMETER
;
1020 if ((Operation
& GCD_MEMORY_SPACE_OPERATION
) != 0) {
1021 CoreAcquireGcdMemoryLock ();
1022 Map
= &mGcdMemorySpaceMap
;
1023 } else if ((Operation
& GCD_IO_SPACE_OPERATION
) != 0) {
1024 CoreAcquireGcdIoLock ();
1025 Map
= &mGcdIoSpaceMap
;
1034 // Compute alignment bit mask
1036 AlignmentMask
= LShiftU64 (1, Alignment
) - 1;
1038 if (GcdAllocateType
== EfiGcdAllocateAddress
) {
1040 // Verify that the BaseAddress passed in is aligned correctly
1042 if ((*BaseAddress
& AlignmentMask
) != 0) {
1043 Status
= EFI_NOT_FOUND
;
1048 // Search for the list of descriptors that cover the range BaseAddress to BaseAddress+Length
1050 Status
= CoreSearchGcdMapEntry (*BaseAddress
, Length
, &StartLink
, &EndLink
, Map
);
1051 if (EFI_ERROR (Status
)) {
1052 Status
= EFI_NOT_FOUND
;
1055 ASSERT (StartLink
!= NULL
&& EndLink
!= NULL
);
1058 // Verify that the list of descriptors are unallocated memory matching GcdMemoryType.
1061 while (Link
!= EndLink
->ForwardLink
) {
1062 Entry
= CR (Link
, EFI_GCD_MAP_ENTRY
, Link
, EFI_GCD_MAP_SIGNATURE
);
1063 Link
= Link
->ForwardLink
;
1064 Status
= CoreAllocateSpaceCheckEntry (Operation
, Entry
, GcdMemoryType
, GcdIoType
);
1065 if (EFI_ERROR (Status
)) {
1072 Entry
= CR (Map
->BackLink
, EFI_GCD_MAP_ENTRY
, Link
, EFI_GCD_MAP_SIGNATURE
);
1075 // Compute the maximum address to use in the search algorithm
1077 if (GcdAllocateType
== EfiGcdAllocateMaxAddressSearchBottomUp
||
1078 GcdAllocateType
== EfiGcdAllocateMaxAddressSearchTopDown
) {
1079 MaxAddress
= *BaseAddress
;
1081 MaxAddress
= Entry
->EndAddress
;
1085 // Verify that the list of descriptors are unallocated memory matching GcdMemoryType.
1087 if (GcdAllocateType
== EfiGcdAllocateMaxAddressSearchTopDown
||
1088 GcdAllocateType
== EfiGcdAllocateAnySearchTopDown
) {
1089 Link
= Map
->BackLink
;
1091 Link
= Map
->ForwardLink
;
1093 while (Link
!= Map
) {
1094 Entry
= CR (Link
, EFI_GCD_MAP_ENTRY
, Link
, EFI_GCD_MAP_SIGNATURE
);
1096 if (GcdAllocateType
== EfiGcdAllocateMaxAddressSearchTopDown
||
1097 GcdAllocateType
== EfiGcdAllocateAnySearchTopDown
) {
1098 Link
= Link
->BackLink
;
1100 Link
= Link
->ForwardLink
;
1103 Status
= CoreAllocateSpaceCheckEntry (Operation
, Entry
, GcdMemoryType
, GcdIoType
);
1104 if (EFI_ERROR (Status
)) {
1108 if (GcdAllocateType
== EfiGcdAllocateMaxAddressSearchTopDown
||
1109 GcdAllocateType
== EfiGcdAllocateAnySearchTopDown
) {
1110 if ((Entry
->BaseAddress
+ Length
) > MaxAddress
) {
1113 if (Length
> (Entry
->EndAddress
+ 1)) {
1114 Status
= EFI_NOT_FOUND
;
1117 if (Entry
->EndAddress
> MaxAddress
) {
1118 *BaseAddress
= MaxAddress
;
1120 *BaseAddress
= Entry
->EndAddress
;
1122 *BaseAddress
= (*BaseAddress
+ 1 - Length
) & (~AlignmentMask
);
1124 *BaseAddress
= (Entry
->BaseAddress
+ AlignmentMask
) & (~AlignmentMask
);
1125 if ((*BaseAddress
+ Length
- 1) > MaxAddress
) {
1126 Status
= EFI_NOT_FOUND
;
1132 // Search for the list of descriptors that cover the range BaseAddress to BaseAddress+Length
1134 Status
= CoreSearchGcdMapEntry (*BaseAddress
, Length
, &StartLink
, &EndLink
, Map
);
1135 if (EFI_ERROR (Status
)) {
1136 Status
= EFI_NOT_FOUND
;
1139 ASSERT (StartLink
!= NULL
&& EndLink
!= NULL
);
1143 // Verify that the list of descriptors are unallocated memory matching GcdMemoryType.
1146 SubLink
= StartLink
;
1147 while (SubLink
!= EndLink
->ForwardLink
) {
1148 Entry
= CR (SubLink
, EFI_GCD_MAP_ENTRY
, Link
, EFI_GCD_MAP_SIGNATURE
);
1149 Status
= CoreAllocateSpaceCheckEntry (Operation
, Entry
, GcdMemoryType
, GcdIoType
);
1150 if (EFI_ERROR (Status
)) {
1155 SubLink
= SubLink
->ForwardLink
;
1163 Status
= EFI_NOT_FOUND
;
1168 // Allocate work space to perform this operation
1170 Status
= CoreAllocateGcdMapEntry (&TopEntry
, &BottomEntry
);
1171 if (EFI_ERROR (Status
)) {
1172 Status
= EFI_OUT_OF_RESOURCES
;
1175 ASSERT (TopEntry
!= NULL
&& BottomEntry
!= NULL
);
1178 // Convert/Insert the list of descriptors from StartLink to EndLink
1181 while (Link
!= EndLink
->ForwardLink
) {
1182 Entry
= CR (Link
, EFI_GCD_MAP_ENTRY
, Link
, EFI_GCD_MAP_SIGNATURE
);
1183 CoreInsertGcdMapEntry (Link
, Entry
, *BaseAddress
, Length
, TopEntry
, BottomEntry
);
1184 Entry
->ImageHandle
= ImageHandle
;
1185 Entry
->DeviceHandle
= DeviceHandle
;
1186 Link
= Link
->ForwardLink
;
1192 Status
= CoreCleanupGcdMapEntry (TopEntry
, BottomEntry
, StartLink
, EndLink
, Map
);
1195 DEBUG ((DEBUG_GCD
, " Status = %r", Status
));
1196 if (!EFI_ERROR (Status
)) {
1197 DEBUG ((DEBUG_GCD
, " (BaseAddress = %016lx)", *BaseAddress
));
1199 DEBUG ((DEBUG_GCD
, "\n"));
1201 if ((Operation
& GCD_MEMORY_SPACE_OPERATION
) != 0) {
1202 CoreReleaseGcdMemoryLock ();
1203 CoreDumpGcdMemorySpaceMap (FALSE
);
1205 if ((Operation
& GCD_IO_SPACE_OPERATION
) !=0) {
1206 CoreReleaseGcdIoLock ();
1207 CoreDumpGcdIoSpaceMap (FALSE
);
1215 Add a segment of memory to GCD map.
1217 @param GcdMemoryType Memory type of the segment.
1218 @param BaseAddress Base address of the segment.
1219 @param Length Length of the segment.
1220 @param Capabilities alterable attributes of the segment.
1222 @retval EFI_INVALID_PARAMETER Invalid parameters.
1223 @retval EFI_SUCCESS Successfully add a segment of memory space.
1227 CoreInternalAddMemorySpace (
1228 IN EFI_GCD_MEMORY_TYPE GcdMemoryType
,
1229 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
1231 IN UINT64 Capabilities
1234 DEBUG ((DEBUG_GCD
, "GCD:AddMemorySpace(Base=%016lx,Length=%016lx)\n", BaseAddress
, Length
));
1235 DEBUG ((DEBUG_GCD
, " GcdMemoryType = %a\n", mGcdMemoryTypeNames
[MIN (GcdMemoryType
, EfiGcdMemoryTypeMaximum
)]));
1236 DEBUG ((DEBUG_GCD
, " Capabilities = %016lx\n", Capabilities
));
1239 // Make sure parameters are valid
1241 if (GcdMemoryType
<= EfiGcdMemoryTypeNonExistent
|| GcdMemoryType
>= EfiGcdMemoryTypeMaximum
) {
1242 return EFI_INVALID_PARAMETER
;
1245 return CoreConvertSpace (GCD_ADD_MEMORY_OPERATION
, GcdMemoryType
, (EFI_GCD_IO_TYPE
) 0, BaseAddress
, Length
, Capabilities
, 0);
1249 // GCD Core Services
1253 Allocates nonexistent memory, reserved memory, system memory, or memorymapped
1254 I/O resources from the global coherency domain of the processor.
1256 @param GcdAllocateType The type of allocate operation
1257 @param GcdMemoryType The desired memory type
1258 @param Alignment Align with 2^Alignment
1259 @param Length Length to allocate
1260 @param BaseAddress Base address to allocate
1261 @param ImageHandle The image handle consume the allocated space.
1262 @param DeviceHandle The device handle consume the allocated space.
1264 @retval EFI_INVALID_PARAMETER Invalid parameter.
1265 @retval EFI_NOT_FOUND No descriptor contains the desired space.
1266 @retval EFI_SUCCESS Memory space successfully allocated.
1271 CoreAllocateMemorySpace (
1272 IN EFI_GCD_ALLOCATE_TYPE GcdAllocateType
,
1273 IN EFI_GCD_MEMORY_TYPE GcdMemoryType
,
1276 IN OUT EFI_PHYSICAL_ADDRESS
*BaseAddress
,
1277 IN EFI_HANDLE ImageHandle
,
1278 IN EFI_HANDLE DeviceHandle OPTIONAL
1281 DEBUG ((DEBUG_GCD
, "GCD:AllocateMemorySpace(Base=%016lx,Length=%016lx)\n", *BaseAddress
, Length
));
1282 DEBUG ((DEBUG_GCD
, " GcdAllocateType = %a\n", mGcdAllocationTypeNames
[MIN (GcdAllocateType
, EfiGcdMaxAllocateType
)]));
1283 DEBUG ((DEBUG_GCD
, " GcdMemoryType = %a\n", mGcdMemoryTypeNames
[MIN (GcdMemoryType
, EfiGcdMemoryTypeMaximum
)]));
1284 DEBUG ((DEBUG_GCD
, " Alignment = %016lx\n", LShiftU64 (1, Alignment
)));
1285 DEBUG ((DEBUG_GCD
, " ImageHandle = %p\n", ImageHandle
));
1286 DEBUG ((DEBUG_GCD
, " DeviceHandle = %p\n", DeviceHandle
));
1288 return CoreAllocateSpace (
1289 GCD_ALLOCATE_MEMORY_OPERATION
,
1292 (EFI_GCD_IO_TYPE
) 0,
1303 Adds reserved memory, system memory, or memory-mapped I/O resources to the
1304 global coherency domain of the processor.
1306 @param GcdMemoryType Memory type of the memory space.
1307 @param BaseAddress Base address of the memory space.
1308 @param Length Length of the memory space.
1309 @param Capabilities alterable attributes of the memory space.
1311 @retval EFI_SUCCESS Merged this memory space into GCD map.
1316 CoreAddMemorySpace (
1317 IN EFI_GCD_MEMORY_TYPE GcdMemoryType
,
1318 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
1320 IN UINT64 Capabilities
1324 EFI_PHYSICAL_ADDRESS PageBaseAddress
;
1327 Status
= CoreInternalAddMemorySpace (GcdMemoryType
, BaseAddress
, Length
, Capabilities
);
1329 if (!EFI_ERROR (Status
) && GcdMemoryType
== EfiGcdMemoryTypeSystemMemory
) {
1331 PageBaseAddress
= PageAlignLength (BaseAddress
);
1332 PageLength
= PageAlignLength (BaseAddress
+ Length
- PageBaseAddress
);
1334 Status
= CoreAllocateMemorySpace (
1335 EfiGcdAllocateAddress
,
1340 gDxeCoreImageHandle
,
1344 if (!EFI_ERROR (Status
)) {
1345 CoreAddMemoryDescriptor (
1346 EfiConventionalMemory
,
1348 RShiftU64 (PageLength
, EFI_PAGE_SHIFT
),
1352 for (; PageLength
!= 0; PageLength
-= EFI_PAGE_SIZE
, PageBaseAddress
+= EFI_PAGE_SIZE
) {
1353 Status
= CoreAllocateMemorySpace (
1354 EfiGcdAllocateAddress
,
1359 gDxeCoreImageHandle
,
1363 if (!EFI_ERROR (Status
)) {
1364 CoreAddMemoryDescriptor (
1365 EfiConventionalMemory
,
1379 Frees nonexistent memory, reserved memory, system memory, or memory-mapped
1380 I/O resources from the global coherency domain of the processor.
1382 @param BaseAddress Base address of the memory space.
1383 @param Length Length of the memory space.
1385 @retval EFI_SUCCESS Space successfully freed.
1390 CoreFreeMemorySpace (
1391 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
1395 DEBUG ((DEBUG_GCD
, "GCD:FreeMemorySpace(Base=%016lx,Length=%016lx)\n", BaseAddress
, Length
));
1397 return CoreConvertSpace (GCD_FREE_MEMORY_OPERATION
, (EFI_GCD_MEMORY_TYPE
) 0, (EFI_GCD_IO_TYPE
) 0, BaseAddress
, Length
, 0, 0);
1402 Removes reserved memory, system memory, or memory-mapped I/O resources from
1403 the global coherency domain of the processor.
1405 @param BaseAddress Base address of the memory space.
1406 @param Length Length of the memory space.
1408 @retval EFI_SUCCESS Successfully remove a segment of memory space.
1413 CoreRemoveMemorySpace (
1414 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
1418 DEBUG ((DEBUG_GCD
, "GCD:RemoveMemorySpace(Base=%016lx,Length=%016lx)\n", BaseAddress
, Length
));
1420 return CoreConvertSpace (GCD_REMOVE_MEMORY_OPERATION
, (EFI_GCD_MEMORY_TYPE
) 0, (EFI_GCD_IO_TYPE
) 0, BaseAddress
, Length
, 0, 0);
1425 Build a memory descriptor according to an entry.
1427 @param Descriptor The descriptor to be built
1428 @param Entry According to this entry
1432 BuildMemoryDescriptor (
1433 IN OUT EFI_GCD_MEMORY_SPACE_DESCRIPTOR
*Descriptor
,
1434 IN EFI_GCD_MAP_ENTRY
*Entry
1437 Descriptor
->BaseAddress
= Entry
->BaseAddress
;
1438 Descriptor
->Length
= Entry
->EndAddress
- Entry
->BaseAddress
+ 1;
1439 Descriptor
->Capabilities
= Entry
->Capabilities
;
1440 Descriptor
->Attributes
= Entry
->Attributes
;
1441 Descriptor
->GcdMemoryType
= Entry
->GcdMemoryType
;
1442 Descriptor
->ImageHandle
= Entry
->ImageHandle
;
1443 Descriptor
->DeviceHandle
= Entry
->DeviceHandle
;
1448 Retrieves the descriptor for a memory region containing a specified address.
1450 @param BaseAddress Specified start address
1451 @param Descriptor Specified length
1453 @retval EFI_INVALID_PARAMETER Invalid parameter
1454 @retval EFI_SUCCESS Successfully get memory space descriptor.
1459 CoreGetMemorySpaceDescriptor (
1460 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
1461 OUT EFI_GCD_MEMORY_SPACE_DESCRIPTOR
*Descriptor
1465 LIST_ENTRY
*StartLink
;
1466 LIST_ENTRY
*EndLink
;
1467 EFI_GCD_MAP_ENTRY
*Entry
;
1470 // Make sure parameters are valid
1472 if (Descriptor
== NULL
) {
1473 return EFI_INVALID_PARAMETER
;
1476 CoreAcquireGcdMemoryLock ();
1479 // Search for the list of descriptors that contain BaseAddress
1481 Status
= CoreSearchGcdMapEntry (BaseAddress
, 1, &StartLink
, &EndLink
, &mGcdMemorySpaceMap
);
1482 if (EFI_ERROR (Status
)) {
1483 Status
= EFI_NOT_FOUND
;
1485 ASSERT (StartLink
!= NULL
&& EndLink
!= NULL
);
1487 // Copy the contents of the found descriptor into Descriptor
1489 Entry
= CR (StartLink
, EFI_GCD_MAP_ENTRY
, Link
, EFI_GCD_MAP_SIGNATURE
);
1490 BuildMemoryDescriptor (Descriptor
, Entry
);
1493 CoreReleaseGcdMemoryLock ();
1500 Modifies the attributes for a memory region in the global coherency domain of the
1503 @param BaseAddress Specified start address
1504 @param Length Specified length
1505 @param Attributes Specified attributes
1507 @retval EFI_SUCCESS Successfully set attribute of a segment of
1513 CoreSetMemorySpaceAttributes (
1514 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
1516 IN UINT64 Attributes
1519 DEBUG ((DEBUG_GCD
, "GCD:SetMemorySpaceAttributes(Base=%016lx,Length=%016lx)\n", BaseAddress
, Length
));
1520 DEBUG ((DEBUG_GCD
, " Attributes = %016lx\n", Attributes
));
1522 return CoreConvertSpace (GCD_SET_ATTRIBUTES_MEMORY_OPERATION
, (EFI_GCD_MEMORY_TYPE
) 0, (EFI_GCD_IO_TYPE
) 0, BaseAddress
, Length
, 0, Attributes
);
1527 Returns a map of the memory resources in the global coherency domain of the
1530 @param NumberOfDescriptors Number of descriptors.
1531 @param MemorySpaceMap Descriptor array
1533 @retval EFI_INVALID_PARAMETER Invalid parameter
1534 @retval EFI_OUT_OF_RESOURCES No enough buffer to allocate
1535 @retval EFI_SUCCESS Successfully get memory space map.
1540 CoreGetMemorySpaceMap (
1541 OUT UINTN
*NumberOfDescriptors
,
1542 OUT EFI_GCD_MEMORY_SPACE_DESCRIPTOR
**MemorySpaceMap
1547 EFI_GCD_MAP_ENTRY
*Entry
;
1548 EFI_GCD_MEMORY_SPACE_DESCRIPTOR
*Descriptor
;
1551 // Make sure parameters are valid
1553 if (NumberOfDescriptors
== NULL
) {
1554 return EFI_INVALID_PARAMETER
;
1556 if (MemorySpaceMap
== NULL
) {
1557 return EFI_INVALID_PARAMETER
;
1560 CoreAcquireGcdMemoryLock ();
1563 // Count the number of descriptors
1565 *NumberOfDescriptors
= CoreCountGcdMapEntry (&mGcdMemorySpaceMap
);
1568 // Allocate the MemorySpaceMap
1570 *MemorySpaceMap
= AllocatePool (*NumberOfDescriptors
* sizeof (EFI_GCD_MEMORY_SPACE_DESCRIPTOR
));
1571 if (*MemorySpaceMap
== NULL
) {
1572 Status
= EFI_OUT_OF_RESOURCES
;
1577 // Fill in the MemorySpaceMap
1579 Descriptor
= *MemorySpaceMap
;
1580 Link
= mGcdMemorySpaceMap
.ForwardLink
;
1581 while (Link
!= &mGcdMemorySpaceMap
) {
1582 Entry
= CR (Link
, EFI_GCD_MAP_ENTRY
, Link
, EFI_GCD_MAP_SIGNATURE
);
1583 BuildMemoryDescriptor (Descriptor
, Entry
);
1585 Link
= Link
->ForwardLink
;
1587 Status
= EFI_SUCCESS
;
1590 CoreReleaseGcdMemoryLock ();
1596 Adds reserved I/O or I/O resources to the global coherency domain of the processor.
1598 @param GcdIoType IO type of the segment.
1599 @param BaseAddress Base address of the segment.
1600 @param Length Length of the segment.
1602 @retval EFI_SUCCESS Merged this segment into GCD map.
1603 @retval EFI_INVALID_PARAMETER Parameter not valid
1609 IN EFI_GCD_IO_TYPE GcdIoType
,
1610 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
1614 DEBUG ((DEBUG_GCD
, "GCD:AddIoSpace(Base=%016lx,Length=%016lx)\n", BaseAddress
, Length
));
1615 DEBUG ((DEBUG_GCD
, " GcdIoType = %a\n", mGcdIoTypeNames
[MIN (GcdIoType
, EfiGcdIoTypeMaximum
)]));
1618 // Make sure parameters are valid
1620 if (GcdIoType
<= EfiGcdIoTypeNonExistent
|| GcdIoType
>= EfiGcdIoTypeMaximum
) {
1621 return EFI_INVALID_PARAMETER
;
1623 return CoreConvertSpace (GCD_ADD_IO_OPERATION
, (EFI_GCD_MEMORY_TYPE
) 0, GcdIoType
, BaseAddress
, Length
, 0, 0);
1628 Allocates nonexistent I/O, reserved I/O, or I/O resources from the global coherency
1629 domain of the processor.
1631 @param GcdAllocateType The type of allocate operation
1632 @param GcdIoType The desired IO type
1633 @param Alignment Align with 2^Alignment
1634 @param Length Length to allocate
1635 @param BaseAddress Base address to allocate
1636 @param ImageHandle The image handle consume the allocated space.
1637 @param DeviceHandle The device handle consume the allocated space.
1639 @retval EFI_INVALID_PARAMETER Invalid parameter.
1640 @retval EFI_NOT_FOUND No descriptor contains the desired space.
1641 @retval EFI_SUCCESS IO space successfully allocated.
1646 CoreAllocateIoSpace (
1647 IN EFI_GCD_ALLOCATE_TYPE GcdAllocateType
,
1648 IN EFI_GCD_IO_TYPE GcdIoType
,
1651 IN OUT EFI_PHYSICAL_ADDRESS
*BaseAddress
,
1652 IN EFI_HANDLE ImageHandle
,
1653 IN EFI_HANDLE DeviceHandle OPTIONAL
1656 DEBUG ((DEBUG_GCD
, "GCD:AllocateIoSpace(Base=%016lx,Length=%016lx)\n", *BaseAddress
, Length
));
1657 DEBUG ((DEBUG_GCD
, " GcdAllocateType = %a\n", mGcdAllocationTypeNames
[MIN (GcdAllocateType
, EfiGcdMaxAllocateType
)]));
1658 DEBUG ((DEBUG_GCD
, " GcdIoType = %a\n", mGcdIoTypeNames
[MIN (GcdIoType
, EfiGcdIoTypeMaximum
)]));
1659 DEBUG ((DEBUG_GCD
, " Alignment = %016lx\n", LShiftU64 (1, Alignment
)));
1660 DEBUG ((DEBUG_GCD
, " ImageHandle = %p\n", ImageHandle
));
1661 DEBUG ((DEBUG_GCD
, " DeviceHandle = %p\n", DeviceHandle
));
1663 return CoreAllocateSpace (
1664 GCD_ALLOCATE_IO_OPERATION
,
1666 (EFI_GCD_MEMORY_TYPE
) 0,
1678 Frees nonexistent I/O, reserved I/O, or I/O resources from the global coherency
1679 domain of the processor.
1681 @param BaseAddress Base address of the segment.
1682 @param Length Length of the segment.
1684 @retval EFI_SUCCESS Space successfully freed.
1690 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
1694 DEBUG ((DEBUG_GCD
, "GCD:FreeIoSpace(Base=%016lx,Length=%016lx)\n", BaseAddress
, Length
));
1696 return CoreConvertSpace (GCD_FREE_IO_OPERATION
, (EFI_GCD_MEMORY_TYPE
) 0, (EFI_GCD_IO_TYPE
) 0, BaseAddress
, Length
, 0, 0);
1701 Removes reserved I/O or I/O resources from the global coherency domain of the
1704 @param BaseAddress Base address of the segment.
1705 @param Length Length of the segment.
1707 @retval EFI_SUCCESS Successfully removed a segment of IO space.
1713 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
1717 DEBUG ((DEBUG_GCD
, "GCD:RemoveIoSpace(Base=%016lx,Length=%016lx)\n", BaseAddress
, Length
));
1719 return CoreConvertSpace (GCD_REMOVE_IO_OPERATION
, (EFI_GCD_MEMORY_TYPE
) 0, (EFI_GCD_IO_TYPE
) 0, BaseAddress
, Length
, 0, 0);
1724 Build a IO descriptor according to an entry.
1726 @param Descriptor The descriptor to be built
1727 @param Entry According to this entry
1732 IN EFI_GCD_IO_SPACE_DESCRIPTOR
*Descriptor
,
1733 IN EFI_GCD_MAP_ENTRY
*Entry
1736 Descriptor
->BaseAddress
= Entry
->BaseAddress
;
1737 Descriptor
->Length
= Entry
->EndAddress
- Entry
->BaseAddress
+ 1;
1738 Descriptor
->GcdIoType
= Entry
->GcdIoType
;
1739 Descriptor
->ImageHandle
= Entry
->ImageHandle
;
1740 Descriptor
->DeviceHandle
= Entry
->DeviceHandle
;
1745 Retrieves the descriptor for an I/O region containing a specified address.
1747 @param BaseAddress Specified start address
1748 @param Descriptor Specified length
1750 @retval EFI_INVALID_PARAMETER Descriptor is NULL.
1751 @retval EFI_SUCCESS Successfully get the IO space descriptor.
1756 CoreGetIoSpaceDescriptor (
1757 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
1758 OUT EFI_GCD_IO_SPACE_DESCRIPTOR
*Descriptor
1762 LIST_ENTRY
*StartLink
;
1763 LIST_ENTRY
*EndLink
;
1764 EFI_GCD_MAP_ENTRY
*Entry
;
1767 // Make sure parameters are valid
1769 if (Descriptor
== NULL
) {
1770 return EFI_INVALID_PARAMETER
;
1773 CoreAcquireGcdIoLock ();
1776 // Search for the list of descriptors that contain BaseAddress
1778 Status
= CoreSearchGcdMapEntry (BaseAddress
, 1, &StartLink
, &EndLink
, &mGcdIoSpaceMap
);
1779 if (EFI_ERROR (Status
)) {
1780 Status
= EFI_NOT_FOUND
;
1782 ASSERT (StartLink
!= NULL
&& EndLink
!= NULL
);
1784 // Copy the contents of the found descriptor into Descriptor
1786 Entry
= CR (StartLink
, EFI_GCD_MAP_ENTRY
, Link
, EFI_GCD_MAP_SIGNATURE
);
1787 BuildIoDescriptor (Descriptor
, Entry
);
1790 CoreReleaseGcdIoLock ();
1797 Returns a map of the I/O resources in the global coherency domain of the processor.
1799 @param NumberOfDescriptors Number of descriptors.
1800 @param IoSpaceMap Descriptor array
1802 @retval EFI_INVALID_PARAMETER Invalid parameter
1803 @retval EFI_OUT_OF_RESOURCES No enough buffer to allocate
1804 @retval EFI_SUCCESS Successfully get IO space map.
1810 OUT UINTN
*NumberOfDescriptors
,
1811 OUT EFI_GCD_IO_SPACE_DESCRIPTOR
**IoSpaceMap
1816 EFI_GCD_MAP_ENTRY
*Entry
;
1817 EFI_GCD_IO_SPACE_DESCRIPTOR
*Descriptor
;
1820 // Make sure parameters are valid
1822 if (NumberOfDescriptors
== NULL
) {
1823 return EFI_INVALID_PARAMETER
;
1825 if (IoSpaceMap
== NULL
) {
1826 return EFI_INVALID_PARAMETER
;
1829 CoreAcquireGcdIoLock ();
1832 // Count the number of descriptors
1834 *NumberOfDescriptors
= CoreCountGcdMapEntry (&mGcdIoSpaceMap
);
1837 // Allocate the IoSpaceMap
1839 *IoSpaceMap
= AllocatePool (*NumberOfDescriptors
* sizeof (EFI_GCD_IO_SPACE_DESCRIPTOR
));
1840 if (*IoSpaceMap
== NULL
) {
1841 Status
= EFI_OUT_OF_RESOURCES
;
1846 // Fill in the IoSpaceMap
1848 Descriptor
= *IoSpaceMap
;
1849 Link
= mGcdIoSpaceMap
.ForwardLink
;
1850 while (Link
!= &mGcdIoSpaceMap
) {
1851 Entry
= CR (Link
, EFI_GCD_MAP_ENTRY
, Link
, EFI_GCD_MAP_SIGNATURE
);
1852 BuildIoDescriptor (Descriptor
, Entry
);
1854 Link
= Link
->ForwardLink
;
1856 Status
= EFI_SUCCESS
;
1859 CoreReleaseGcdIoLock ();
1865 Converts a Resource Descriptor HOB attributes mask to an EFI Memory Descriptor
1868 @param GcdMemoryType Type of resource in the GCD memory map.
1869 @param Attributes The attribute mask in the Resource Descriptor
1872 @return The capabilities mask for an EFI Memory Descriptor.
1876 CoreConvertResourceDescriptorHobAttributesToCapabilities (
1877 EFI_GCD_MEMORY_TYPE GcdMemoryType
,
1881 UINT64 Capabilities
;
1882 GCD_ATTRIBUTE_CONVERSION_ENTRY
*Conversion
;
1885 // Convert the Resource HOB Attributes to an EFI Memory Capabilities mask
1887 for (Capabilities
= 0, Conversion
= mAttributeConversionTable
; Conversion
->Attribute
!= 0; Conversion
++) {
1888 if (Conversion
->Memory
|| (GcdMemoryType
!= EfiGcdMemoryTypeSystemMemory
)) {
1889 if (Attributes
& Conversion
->Attribute
) {
1890 Capabilities
|= Conversion
->Capability
;
1895 return Capabilities
;
1900 External function. Initializes memory services based on the memory
1901 descriptor HOBs. This function is responsible for priming the memory
1902 map, so memory allocations and resource allocations can be made.
1903 The first part of this function can not depend on any memory services
1904 until at least one memory descriptor is provided to the memory services.
1906 @param HobStart The start address of the HOB.
1907 @param MemoryBaseAddress Start address of memory region found to init DXE
1909 @param MemoryLength Length of memory region found to init DXE core.
1911 @retval EFI_SUCCESS Memory services successfully initialized.
1915 CoreInitializeMemoryServices (
1917 OUT EFI_PHYSICAL_ADDRESS
*MemoryBaseAddress
,
1918 OUT UINT64
*MemoryLength
1921 EFI_PEI_HOB_POINTERS Hob
;
1922 EFI_MEMORY_TYPE_INFORMATION
*EfiMemoryTypeInformation
;
1925 EFI_HOB_HANDOFF_INFO_TABLE
*PhitHob
;
1926 EFI_HOB_RESOURCE_DESCRIPTOR
*ResourceHob
;
1927 EFI_HOB_RESOURCE_DESCRIPTOR
*PhitResourceHob
;
1928 EFI_PHYSICAL_ADDRESS BaseAddress
;
1931 UINT64 Capabilities
;
1932 EFI_PHYSICAL_ADDRESS MaxMemoryBaseAddress
;
1933 UINT64 MaxMemoryLength
;
1934 UINT64 MaxMemoryAttributes
;
1935 EFI_PHYSICAL_ADDRESS TestedMemoryBaseAddress
;
1936 UINT64 TestedMemoryLength
;
1937 EFI_PHYSICAL_ADDRESS HighAddress
;
1938 EFI_HOB_GUID_TYPE
*GuidHob
;
1939 UINT32 ReservedCodePageNumber
;
1942 // Point at the first HOB. This must be the PHIT HOB.
1944 Hob
.Raw
= *HobStart
;
1945 ASSERT (GET_HOB_TYPE (Hob
) == EFI_HOB_TYPE_HANDOFF
);
1948 // Initialize the spin locks and maps in the memory services.
1949 // Also fill in the memory services into the EFI Boot Services Table
1951 CoreInitializePool ();
1954 // Initialize Local Variables
1956 PhitResourceHob
= NULL
;
1961 MaxMemoryBaseAddress
= 0;
1962 MaxMemoryLength
= 0;
1963 MaxMemoryAttributes
= 0;
1966 // Cache the PHIT HOB for later use
1968 PhitHob
= Hob
.HandoffInformationTable
;
1970 if (PcdGet64(PcdLoadModuleAtFixAddressEnable
) != 0) {
1971 ReservedCodePageNumber
= PcdGet32(PcdLoadFixAddressRuntimeCodePageNumber
);
1972 ReservedCodePageNumber
+= PcdGet32(PcdLoadFixAddressBootTimeCodePageNumber
);
1975 // cache the Top address for loading modules at Fixed Address
1977 gLoadModuleAtFixAddressConfigurationTable
.DxeCodeTopAddress
= PhitHob
->EfiMemoryTop
1978 + EFI_PAGES_TO_SIZE(ReservedCodePageNumber
);
1981 // See if a Memory Type Information HOB is available
1983 GuidHob
= GetFirstGuidHob (&gEfiMemoryTypeInformationGuid
);
1984 if (GuidHob
!= NULL
) {
1985 EfiMemoryTypeInformation
= GET_GUID_HOB_DATA (GuidHob
);
1986 DataSize
= GET_GUID_HOB_DATA_SIZE (GuidHob
);
1987 if (EfiMemoryTypeInformation
!= NULL
&& DataSize
> 0 && DataSize
<= (EfiMaxMemoryType
+ 1) * sizeof (EFI_MEMORY_TYPE_INFORMATION
)) {
1988 CopyMem (&gMemoryTypeInformation
, EfiMemoryTypeInformation
, DataSize
);
1993 // Find the Resource Descriptor HOB that contains PHIT range EfiFreeMemoryBottom..EfiFreeMemoryTop
1997 for (Hob
.Raw
= *HobStart
; !END_OF_HOB_LIST(Hob
); Hob
.Raw
= GET_NEXT_HOB(Hob
)) {
1999 // Skip all HOBs except Resource Descriptor HOBs
2001 if (GET_HOB_TYPE (Hob
) != EFI_HOB_TYPE_RESOURCE_DESCRIPTOR
) {
2006 // Skip Resource Descriptor HOBs that do not describe tested system memory
2008 ResourceHob
= Hob
.ResourceDescriptor
;
2009 if (ResourceHob
->ResourceType
!= EFI_RESOURCE_SYSTEM_MEMORY
) {
2012 if ((ResourceHob
->ResourceAttribute
& MEMORY_ATTRIBUTE_MASK
) != TESTED_MEMORY_ATTRIBUTES
) {
2017 // Skip Resource Descriptor HOBs that do not contain the PHIT range EfiFreeMemoryBottom..EfiFreeMemoryTop
2019 if (PhitHob
->EfiFreeMemoryBottom
< ResourceHob
->PhysicalStart
) {
2022 if (PhitHob
->EfiFreeMemoryTop
> (ResourceHob
->PhysicalStart
+ ResourceHob
->ResourceLength
)) {
2027 // Cache the resource descriptor HOB for the memory region described by the PHIT HOB
2029 PhitResourceHob
= ResourceHob
;
2033 // Compute range between PHIT EfiFreeMemoryTop and the end of the Resource Descriptor HOB
2035 Attributes
= PhitResourceHob
->ResourceAttribute
;
2036 BaseAddress
= PageAlignAddress (PhitHob
->EfiMemoryTop
);
2037 Length
= PageAlignLength (ResourceHob
->PhysicalStart
+ ResourceHob
->ResourceLength
- BaseAddress
);
2038 if (Length
< MINIMUM_INITIAL_MEMORY_SIZE
) {
2040 // If that range is not large enough to intialize the DXE Core, then
2041 // Compute range between PHIT EfiFreeMemoryBottom and PHIT EfiFreeMemoryTop
2043 BaseAddress
= PageAlignAddress (PhitHob
->EfiFreeMemoryBottom
);
2044 Length
= PageAlignLength (PhitHob
->EfiFreeMemoryTop
- BaseAddress
);
2045 if (Length
< MINIMUM_INITIAL_MEMORY_SIZE
) {
2047 // If that range is not large enough to intialize the DXE Core, then
2048 // Compute range between the start of the Resource Descriptor HOB and the start of the HOB List
2050 BaseAddress
= PageAlignAddress (ResourceHob
->PhysicalStart
);
2051 Length
= PageAlignLength ((UINT64
)((UINTN
)*HobStart
- BaseAddress
));
2058 // Assert if a resource descriptor HOB for the memory region described by the PHIT was not found
2063 // Search all the resource descriptor HOBs from the highest possible addresses down for a memory
2064 // region that is big enough to initialize the DXE core. Always skip the PHIT Resource HOB.
2065 // The max address must be within the physically addressible range for the processor.
2067 HighAddress
= MAX_ADDRESS
;
2068 for (Hob
.Raw
= *HobStart
; !END_OF_HOB_LIST(Hob
); Hob
.Raw
= GET_NEXT_HOB(Hob
)) {
2070 // Skip the Resource Descriptor HOB that contains the PHIT
2072 if (Hob
.ResourceDescriptor
== PhitResourceHob
) {
2076 // Skip all HOBs except Resource Descriptor HOBs
2078 if (GET_HOB_TYPE (Hob
) != EFI_HOB_TYPE_RESOURCE_DESCRIPTOR
) {
2083 // Skip Resource Descriptor HOBs that do not describe tested system memory below MAX_ADDRESS
2085 ResourceHob
= Hob
.ResourceDescriptor
;
2086 if (ResourceHob
->ResourceType
!= EFI_RESOURCE_SYSTEM_MEMORY
) {
2089 if ((ResourceHob
->ResourceAttribute
& MEMORY_ATTRIBUTE_MASK
) != TESTED_MEMORY_ATTRIBUTES
) {
2092 if ((ResourceHob
->PhysicalStart
+ ResourceHob
->ResourceLength
) > (EFI_PHYSICAL_ADDRESS
)MAX_ADDRESS
) {
2097 // Skip Resource Descriptor HOBs that are below a previously found Resource Descriptor HOB
2099 if (HighAddress
!= (EFI_PHYSICAL_ADDRESS
)MAX_ADDRESS
&& ResourceHob
->PhysicalStart
<= HighAddress
) {
2104 // Skip Resource Descriptor HOBs that are not large enough to initilize the DXE Core
2106 TestedMemoryBaseAddress
= PageAlignAddress (ResourceHob
->PhysicalStart
);
2107 TestedMemoryLength
= PageAlignLength (ResourceHob
->PhysicalStart
+ ResourceHob
->ResourceLength
- TestedMemoryBaseAddress
);
2108 if (TestedMemoryLength
< MINIMUM_INITIAL_MEMORY_SIZE
) {
2113 // Save the Resource Descriptor HOB context that is large enough to initilize the DXE Core
2115 MaxMemoryBaseAddress
= TestedMemoryBaseAddress
;
2116 MaxMemoryLength
= TestedMemoryLength
;
2117 MaxMemoryAttributes
= ResourceHob
->ResourceAttribute
;
2118 HighAddress
= ResourceHob
->PhysicalStart
;
2122 // If Length is not large enough to initialize the DXE Core or a Resource
2123 // Descriptor HOB was found above the PHIT HOB that is large enough to initialize
2124 // the DXE Core, then use the range described by the Resource Descriptor
2125 // HOB that was found above the PHIT HOB.
2127 if ((Length
< MINIMUM_INITIAL_MEMORY_SIZE
) ||
2128 (MaxMemoryBaseAddress
> BaseAddress
&& MaxMemoryLength
>= MINIMUM_INITIAL_MEMORY_SIZE
)) {
2129 BaseAddress
= MaxMemoryBaseAddress
;
2130 Length
= MaxMemoryLength
;
2131 Attributes
= MaxMemoryAttributes
;
2135 // If no memory regions are found that are big enough to initialize the DXE core, then ASSERT().
2137 ASSERT (Length
>= MINIMUM_INITIAL_MEMORY_SIZE
);
2140 // Convert the Resource HOB Attributes to an EFI Memory Capabilities mask
2142 Capabilities
= CoreConvertResourceDescriptorHobAttributesToCapabilities (EfiGcdMemoryTypeSystemMemory
, Attributes
);
2145 // Declare the very first memory region, so the EFI Memory Services are available.
2147 CoreAddMemoryDescriptor (
2148 EfiConventionalMemory
,
2150 RShiftU64 (Length
, EFI_PAGE_SHIFT
),
2154 *MemoryBaseAddress
= BaseAddress
;
2155 *MemoryLength
= Length
;
2162 External function. Initializes the GCD and memory services based on the memory
2163 descriptor HOBs. This function is responsible for priming the GCD map and the
2164 memory map, so memory allocations and resource allocations can be made. The
2165 HobStart will be relocated to a pool buffer.
2167 @param HobStart The start address of the HOB
2168 @param MemoryBaseAddress Start address of memory region found to init DXE
2170 @param MemoryLength Length of memory region found to init DXE core.
2172 @retval EFI_SUCCESS GCD services successfully initialized.
2176 CoreInitializeGcdServices (
2177 IN OUT VOID
**HobStart
,
2178 IN EFI_PHYSICAL_ADDRESS MemoryBaseAddress
,
2179 IN UINT64 MemoryLength
2182 EFI_PEI_HOB_POINTERS Hob
;
2184 EFI_HOB_HANDOFF_INFO_TABLE
*PhitHob
;
2185 UINT8 SizeOfMemorySpace
;
2186 UINT8 SizeOfIoSpace
;
2187 EFI_HOB_RESOURCE_DESCRIPTOR
*ResourceHob
;
2188 EFI_PHYSICAL_ADDRESS BaseAddress
;
2191 EFI_GCD_MAP_ENTRY
*Entry
;
2192 EFI_GCD_MEMORY_TYPE GcdMemoryType
;
2193 EFI_GCD_IO_TYPE GcdIoType
;
2194 EFI_GCD_MEMORY_SPACE_DESCRIPTOR Descriptor
;
2195 EFI_HOB_MEMORY_ALLOCATION
*MemoryHob
;
2196 EFI_HOB_FIRMWARE_VOLUME
*FirmwareVolumeHob
;
2197 UINTN NumberOfDescriptors
;
2198 EFI_GCD_MEMORY_SPACE_DESCRIPTOR
*MemorySpaceMap
;
2200 UINT64 Capabilities
;
2201 EFI_HOB_CPU
* CpuHob
;
2204 // Cache the PHIT HOB for later use
2206 PhitHob
= (EFI_HOB_HANDOFF_INFO_TABLE
*)(*HobStart
);
2209 // Get the number of address lines in the I/O and Memory space for the CPU
2211 CpuHob
= GetFirstHob (EFI_HOB_TYPE_CPU
);
2212 ASSERT (CpuHob
!= NULL
);
2213 SizeOfMemorySpace
= CpuHob
->SizeOfMemorySpace
;
2214 SizeOfIoSpace
= CpuHob
->SizeOfIoSpace
;
2217 // Initialize the GCD Memory Space Map
2219 Entry
= AllocateCopyPool (sizeof (EFI_GCD_MAP_ENTRY
), &mGcdMemorySpaceMapEntryTemplate
);
2220 ASSERT (Entry
!= NULL
);
2222 Entry
->EndAddress
= LShiftU64 (1, SizeOfMemorySpace
) - 1;
2224 InsertHeadList (&mGcdMemorySpaceMap
, &Entry
->Link
);
2226 CoreDumpGcdMemorySpaceMap (TRUE
);
2229 // Initialize the GCD I/O Space Map
2231 Entry
= AllocateCopyPool (sizeof (EFI_GCD_MAP_ENTRY
), &mGcdIoSpaceMapEntryTemplate
);
2232 ASSERT (Entry
!= NULL
);
2234 Entry
->EndAddress
= LShiftU64 (1, SizeOfIoSpace
) - 1;
2236 InsertHeadList (&mGcdIoSpaceMap
, &Entry
->Link
);
2238 CoreDumpGcdIoSpaceMap (TRUE
);
2241 // Walk the HOB list and add all resource descriptors to the GCD
2243 for (Hob
.Raw
= *HobStart
; !END_OF_HOB_LIST(Hob
); Hob
.Raw
= GET_NEXT_HOB(Hob
)) {
2245 GcdMemoryType
= EfiGcdMemoryTypeNonExistent
;
2246 GcdIoType
= EfiGcdIoTypeNonExistent
;
2248 if (GET_HOB_TYPE (Hob
) == EFI_HOB_TYPE_RESOURCE_DESCRIPTOR
) {
2250 ResourceHob
= Hob
.ResourceDescriptor
;
2252 switch (ResourceHob
->ResourceType
) {
2253 case EFI_RESOURCE_SYSTEM_MEMORY
:
2254 if ((ResourceHob
->ResourceAttribute
& MEMORY_ATTRIBUTE_MASK
) == TESTED_MEMORY_ATTRIBUTES
) {
2255 GcdMemoryType
= EfiGcdMemoryTypeSystemMemory
;
2257 if ((ResourceHob
->ResourceAttribute
& MEMORY_ATTRIBUTE_MASK
) == INITIALIZED_MEMORY_ATTRIBUTES
) {
2258 GcdMemoryType
= EfiGcdMemoryTypeReserved
;
2260 if ((ResourceHob
->ResourceAttribute
& MEMORY_ATTRIBUTE_MASK
) == PRESENT_MEMORY_ATTRIBUTES
) {
2261 GcdMemoryType
= EfiGcdMemoryTypeReserved
;
2264 case EFI_RESOURCE_MEMORY_MAPPED_IO
:
2265 case EFI_RESOURCE_FIRMWARE_DEVICE
:
2266 GcdMemoryType
= EfiGcdMemoryTypeMemoryMappedIo
;
2268 case EFI_RESOURCE_MEMORY_MAPPED_IO_PORT
:
2269 case EFI_RESOURCE_MEMORY_RESERVED
:
2270 GcdMemoryType
= EfiGcdMemoryTypeReserved
;
2272 case EFI_RESOURCE_IO
:
2273 GcdIoType
= EfiGcdIoTypeIo
;
2275 case EFI_RESOURCE_IO_RESERVED
:
2276 GcdIoType
= EfiGcdIoTypeReserved
;
2280 if (GcdMemoryType
!= EfiGcdMemoryTypeNonExistent
) {
2282 // Convert the Resource HOB Attributes to an EFI Memory Capabilities mask
2284 Capabilities
= CoreConvertResourceDescriptorHobAttributesToCapabilities (
2286 ResourceHob
->ResourceAttribute
2289 Status
= CoreInternalAddMemorySpace (
2291 ResourceHob
->PhysicalStart
,
2292 ResourceHob
->ResourceLength
,
2297 if (GcdIoType
!= EfiGcdIoTypeNonExistent
) {
2298 Status
= CoreAddIoSpace (
2300 ResourceHob
->PhysicalStart
,
2301 ResourceHob
->ResourceLength
2308 // Allocate first memory region from the GCD by the DXE core
2310 Status
= CoreAllocateMemorySpace (
2311 EfiGcdAllocateAddress
,
2312 EfiGcdMemoryTypeSystemMemory
,
2316 gDxeCoreImageHandle
,
2321 // Walk the HOB list and allocate all memory space that is consumed by memory allocation HOBs,
2322 // and Firmware Volume HOBs. Also update the EFI Memory Map with the memory allocation HOBs.
2324 for (Hob
.Raw
= *HobStart
; !END_OF_HOB_LIST(Hob
); Hob
.Raw
= GET_NEXT_HOB(Hob
)) {
2325 if (GET_HOB_TYPE (Hob
) == EFI_HOB_TYPE_MEMORY_ALLOCATION
) {
2326 MemoryHob
= Hob
.MemoryAllocation
;
2327 BaseAddress
= MemoryHob
->AllocDescriptor
.MemoryBaseAddress
;
2328 Status
= CoreGetMemorySpaceDescriptor (BaseAddress
, &Descriptor
);
2329 if (!EFI_ERROR (Status
)) {
2330 Status
= CoreAllocateMemorySpace (
2331 EfiGcdAllocateAddress
,
2332 Descriptor
.GcdMemoryType
,
2334 MemoryHob
->AllocDescriptor
.MemoryLength
,
2336 gDxeCoreImageHandle
,
2339 if (!EFI_ERROR (Status
) && Descriptor
.GcdMemoryType
== EfiGcdMemoryTypeSystemMemory
) {
2340 CoreAddMemoryDescriptor (
2341 MemoryHob
->AllocDescriptor
.MemoryType
,
2342 MemoryHob
->AllocDescriptor
.MemoryBaseAddress
,
2343 RShiftU64 (MemoryHob
->AllocDescriptor
.MemoryLength
, EFI_PAGE_SHIFT
),
2344 Descriptor
.Capabilities
& (~EFI_MEMORY_RUNTIME
)
2350 if (GET_HOB_TYPE (Hob
) == EFI_HOB_TYPE_FV
) {
2351 FirmwareVolumeHob
= Hob
.FirmwareVolume
;
2352 BaseAddress
= FirmwareVolumeHob
->BaseAddress
;
2353 Status
= CoreAllocateMemorySpace (
2354 EfiGcdAllocateAddress
,
2355 EfiGcdMemoryTypeMemoryMappedIo
,
2357 FirmwareVolumeHob
->Length
,
2359 gDxeCoreImageHandle
,
2366 // Relocate HOB List to an allocated pool buffer.
2368 NewHobList
= AllocateCopyPool (
2369 (UINTN
)PhitHob
->EfiFreeMemoryBottom
- (UINTN
)(*HobStart
),
2372 ASSERT (NewHobList
!= NULL
);
2374 *HobStart
= NewHobList
;
2375 gHobList
= NewHobList
;
2378 // Add and allocate the remaining unallocated system memory to the memory services.
2380 Status
= CoreGetMemorySpaceMap (&NumberOfDescriptors
, &MemorySpaceMap
);
2381 ASSERT (Status
== EFI_SUCCESS
);
2383 for (Index
= 0; Index
< NumberOfDescriptors
; Index
++) {
2384 if (MemorySpaceMap
[Index
].GcdMemoryType
== EfiGcdMemoryTypeSystemMemory
) {
2385 if (MemorySpaceMap
[Index
].ImageHandle
== NULL
) {
2386 BaseAddress
= PageAlignAddress (MemorySpaceMap
[Index
].BaseAddress
);
2387 Length
= PageAlignLength (MemorySpaceMap
[Index
].BaseAddress
+ MemorySpaceMap
[Index
].Length
- BaseAddress
);
2388 if (Length
== 0 || MemorySpaceMap
[Index
].BaseAddress
+ MemorySpaceMap
[Index
].Length
< BaseAddress
) {
2391 CoreAddMemoryDescriptor (
2392 EfiConventionalMemory
,
2394 RShiftU64 (Length
, EFI_PAGE_SHIFT
),
2395 MemorySpaceMap
[Index
].Capabilities
& (~EFI_MEMORY_RUNTIME
)
2397 Status
= CoreAllocateMemorySpace (
2398 EfiGcdAllocateAddress
,
2399 EfiGcdMemoryTypeSystemMemory
,
2403 gDxeCoreImageHandle
,
2409 CoreFreePool (MemorySpaceMap
);