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);
396 ASSERT (TopEntry
->Signature
== 0);
397 ASSERT (BottomEntry
->Signature
== 0);
399 if (BaseAddress
> Entry
->BaseAddress
) {
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 CopyMem (TopEntry
, Entry
, sizeof (EFI_GCD_MAP_ENTRY
));
408 TopEntry
->BaseAddress
= BaseAddress
+ Length
;
409 Entry
->EndAddress
= BaseAddress
+ Length
- 1;
410 InsertHeadList (Link
, &TopEntry
->Link
);
418 Merge the Gcd region specified by Link and its adjacent entry.
420 @param Link Specify the entry to be merged (with its
422 @param Forward Direction (forward or backward).
425 @retval EFI_SUCCESS Successfully returned.
426 @retval EFI_UNSUPPORTED These adjacent regions could not merge.
430 CoreMergeGcdMapEntry (
436 LIST_ENTRY
*AdjacentLink
;
437 EFI_GCD_MAP_ENTRY
*Entry
;
438 EFI_GCD_MAP_ENTRY
*AdjacentEntry
;
441 // Get adjacent entry
444 AdjacentLink
= Link
->ForwardLink
;
446 AdjacentLink
= Link
->BackLink
;
450 // If AdjacentLink is the head of the list, then no merge can be performed
452 if (AdjacentLink
== Map
) {
456 Entry
= CR (Link
, EFI_GCD_MAP_ENTRY
, Link
, EFI_GCD_MAP_SIGNATURE
);
457 AdjacentEntry
= CR (AdjacentLink
, EFI_GCD_MAP_ENTRY
, Link
, EFI_GCD_MAP_SIGNATURE
);
459 if (Entry
->Capabilities
!= AdjacentEntry
->Capabilities
) {
460 return EFI_UNSUPPORTED
;
462 if (Entry
->Attributes
!= AdjacentEntry
->Attributes
) {
463 return EFI_UNSUPPORTED
;
465 if (Entry
->GcdMemoryType
!= AdjacentEntry
->GcdMemoryType
) {
466 return EFI_UNSUPPORTED
;
468 if (Entry
->GcdIoType
!= AdjacentEntry
->GcdIoType
) {
469 return EFI_UNSUPPORTED
;
471 if (Entry
->ImageHandle
!= AdjacentEntry
->ImageHandle
) {
472 return EFI_UNSUPPORTED
;
474 if (Entry
->DeviceHandle
!= AdjacentEntry
->DeviceHandle
) {
475 return EFI_UNSUPPORTED
;
479 Entry
->EndAddress
= AdjacentEntry
->EndAddress
;
481 Entry
->BaseAddress
= AdjacentEntry
->BaseAddress
;
483 RemoveEntryList (AdjacentLink
);
484 CoreFreePool (AdjacentEntry
);
491 Merge adjacent entries on total chain.
493 @param TopEntry Top entry of GCD map.
494 @param BottomEntry Bottom entry of GCD map.
495 @param StartLink Start link of the list for this loop.
496 @param EndLink End link of the list for this loop.
499 @retval EFI_SUCCESS GCD map successfully cleaned up.
503 CoreCleanupGcdMapEntry (
504 IN EFI_GCD_MAP_ENTRY
*TopEntry
,
505 IN EFI_GCD_MAP_ENTRY
*BottomEntry
,
506 IN LIST_ENTRY
*StartLink
,
507 IN LIST_ENTRY
*EndLink
,
513 if (TopEntry
->Signature
== 0) {
514 CoreFreePool (TopEntry
);
516 if (BottomEntry
->Signature
== 0) {
517 CoreFreePool (BottomEntry
);
521 while (Link
!= EndLink
->ForwardLink
) {
522 CoreMergeGcdMapEntry (Link
, FALSE
, Map
);
523 Link
= Link
->ForwardLink
;
525 CoreMergeGcdMapEntry (EndLink
, TRUE
, Map
);
532 Search a segment of memory space in GCD map. The result is a range of GCD entry list.
534 @param BaseAddress The start address of the segment.
535 @param Length The length of the segment.
536 @param StartLink The first GCD entry involves this segment of
538 @param EndLink The first GCD entry involves this segment of
540 @param Map Points to the start entry to search.
542 @retval EFI_SUCCESS Successfully found the entry.
543 @retval EFI_NOT_FOUND Not found.
547 CoreSearchGcdMapEntry (
548 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
550 OUT LIST_ENTRY
**StartLink
,
551 OUT LIST_ENTRY
**EndLink
,
556 EFI_GCD_MAP_ENTRY
*Entry
;
558 ASSERT (Length
!= 0);
563 Link
= Map
->ForwardLink
;
564 while (Link
!= Map
) {
565 Entry
= CR (Link
, EFI_GCD_MAP_ENTRY
, Link
, EFI_GCD_MAP_SIGNATURE
);
566 if (BaseAddress
>= Entry
->BaseAddress
&& BaseAddress
<= Entry
->EndAddress
) {
569 if (*StartLink
!= NULL
) {
570 if ((BaseAddress
+ Length
- 1) >= Entry
->BaseAddress
&&
571 (BaseAddress
+ Length
- 1) <= Entry
->EndAddress
) {
576 Link
= Link
->ForwardLink
;
579 return EFI_NOT_FOUND
;
584 Count the amount of GCD map entries.
586 @param Map Points to the start entry to do the count loop.
592 CoreCountGcdMapEntry (
600 Link
= Map
->ForwardLink
;
601 while (Link
!= Map
) {
603 Link
= Link
->ForwardLink
;
612 Return the memory attribute specified by Attributes
614 @param Attributes A num with some attribute bits on.
616 @return The enum value of memory attribute.
620 ConverToCpuArchAttributes (
624 if ( (Attributes
& EFI_MEMORY_UC
) == EFI_MEMORY_UC
) {
625 return EFI_MEMORY_UC
;
628 if ( (Attributes
& EFI_MEMORY_WC
) == EFI_MEMORY_WC
) {
629 return EFI_MEMORY_WC
;
632 if ( (Attributes
& EFI_MEMORY_WT
) == EFI_MEMORY_WT
) {
633 return EFI_MEMORY_WT
;
636 if ( (Attributes
& EFI_MEMORY_WB
) == EFI_MEMORY_WB
) {
637 return EFI_MEMORY_WB
;
640 if ( (Attributes
& EFI_MEMORY_WP
) == EFI_MEMORY_WP
) {
641 return EFI_MEMORY_WP
;
644 return INVALID_CPU_ARCH_ATTRIBUTES
;
650 Do operation on a segment of memory space specified (add, free, remove, change attribute ...).
652 @param Operation The type of the operation
653 @param GcdMemoryType Additional information for the operation
654 @param GcdIoType Additional information for the operation
655 @param BaseAddress Start address of the segment
656 @param Length length of the segment
657 @param Capabilities The alterable attributes of a newly added entry
658 @param Attributes The attributes needs to be set
660 @retval EFI_INVALID_PARAMETER Length is 0 or address (length) not aligned when
662 @retval EFI_SUCCESS Action successfully done.
663 @retval EFI_UNSUPPORTED Could not find the proper descriptor on this
664 segment or set an upsupported attribute.
665 @retval EFI_ACCESS_DENIED Operate on an space non-exist or is used for an
667 @retval EFI_NOT_FOUND Free a non-using space or remove a non-exist
669 @retval EFI_OUT_OF_RESOURCES No buffer could be allocated.
675 IN EFI_GCD_MEMORY_TYPE GcdMemoryType
,
676 IN EFI_GCD_IO_TYPE GcdIoType
,
677 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
679 IN UINT64 Capabilities
,
686 EFI_GCD_MAP_ENTRY
*Entry
;
687 EFI_GCD_MAP_ENTRY
*TopEntry
;
688 EFI_GCD_MAP_ENTRY
*BottomEntry
;
689 LIST_ENTRY
*StartLink
;
691 UINT64 CpuArchAttributes
;
694 DEBUG ((DEBUG_GCD
, " Status = %r\n", EFI_INVALID_PARAMETER
));
695 return EFI_INVALID_PARAMETER
;
699 if ((Operation
& GCD_MEMORY_SPACE_OPERATION
) != 0) {
700 CoreAcquireGcdMemoryLock ();
701 Map
= &mGcdMemorySpaceMap
;
702 } else if ((Operation
& GCD_IO_SPACE_OPERATION
) != 0) {
703 CoreAcquireGcdIoLock ();
704 Map
= &mGcdIoSpaceMap
;
710 // Search for the list of descriptors that cover the range BaseAddress to BaseAddress+Length
712 Status
= CoreSearchGcdMapEntry (BaseAddress
, Length
, &StartLink
, &EndLink
, Map
);
713 if (EFI_ERROR (Status
)) {
714 Status
= EFI_UNSUPPORTED
;
718 ASSERT (StartLink
!= NULL
&& EndLink
!= NULL
);
721 // Verify that the list of descriptors are unallocated non-existent memory.
724 while (Link
!= EndLink
->ForwardLink
) {
725 Entry
= CR (Link
, EFI_GCD_MAP_ENTRY
, Link
, EFI_GCD_MAP_SIGNATURE
);
730 case GCD_ADD_MEMORY_OPERATION
:
731 if (Entry
->GcdMemoryType
!= EfiGcdMemoryTypeNonExistent
||
732 Entry
->ImageHandle
!= NULL
) {
733 Status
= EFI_ACCESS_DENIED
;
737 case GCD_ADD_IO_OPERATION
:
738 if (Entry
->GcdIoType
!= EfiGcdIoTypeNonExistent
||
739 Entry
->ImageHandle
!= NULL
) {
740 Status
= EFI_ACCESS_DENIED
;
747 case GCD_FREE_MEMORY_OPERATION
:
748 case GCD_FREE_IO_OPERATION
:
749 if (Entry
->ImageHandle
== NULL
) {
750 Status
= EFI_NOT_FOUND
;
757 case GCD_REMOVE_MEMORY_OPERATION
:
758 if (Entry
->GcdMemoryType
== EfiGcdMemoryTypeNonExistent
) {
759 Status
= EFI_NOT_FOUND
;
762 if (Entry
->ImageHandle
!= NULL
) {
763 Status
= EFI_ACCESS_DENIED
;
767 case GCD_REMOVE_IO_OPERATION
:
768 if (Entry
->GcdIoType
== EfiGcdIoTypeNonExistent
) {
769 Status
= EFI_NOT_FOUND
;
772 if (Entry
->ImageHandle
!= NULL
) {
773 Status
= EFI_ACCESS_DENIED
;
778 // Set attribute operations
780 case GCD_SET_ATTRIBUTES_MEMORY_OPERATION
:
781 if ((Attributes
& EFI_MEMORY_RUNTIME
) != 0) {
782 if ((BaseAddress
& EFI_PAGE_MASK
) != 0 || (Length
& EFI_PAGE_MASK
) != 0) {
783 Status
= EFI_INVALID_PARAMETER
;
787 if ((Entry
->Capabilities
& Attributes
) != Attributes
) {
788 Status
= EFI_UNSUPPORTED
;
793 Link
= Link
->ForwardLink
;
797 // Allocate work space to perform this operation
799 Status
= CoreAllocateGcdMapEntry (&TopEntry
, &BottomEntry
);
800 if (EFI_ERROR (Status
)) {
801 Status
= EFI_OUT_OF_RESOURCES
;
804 ASSERT (TopEntry
!= NULL
&& BottomEntry
!= NULL
);
806 if (Operation
== GCD_SET_ATTRIBUTES_MEMORY_OPERATION
) {
808 // Call CPU Arch Protocol to attempt to set attributes on the range
810 CpuArchAttributes
= ConverToCpuArchAttributes (Attributes
);
811 if (CpuArchAttributes
!= INVALID_CPU_ARCH_ATTRIBUTES
) {
813 Status
= gCpu
->SetMemoryAttributes (
819 if (EFI_ERROR (Status
)) {
827 // Convert/Insert the list of descriptors from StartLink to EndLink
830 while (Link
!= EndLink
->ForwardLink
) {
831 Entry
= CR (Link
, EFI_GCD_MAP_ENTRY
, Link
, EFI_GCD_MAP_SIGNATURE
);
832 CoreInsertGcdMapEntry (Link
, Entry
, BaseAddress
, Length
, TopEntry
, BottomEntry
);
837 case GCD_ADD_MEMORY_OPERATION
:
838 Entry
->GcdMemoryType
= GcdMemoryType
;
839 if (GcdMemoryType
== EfiGcdMemoryTypeMemoryMappedIo
) {
840 Entry
->Capabilities
= Capabilities
| EFI_MEMORY_RUNTIME
| EFI_MEMORY_PORT_IO
;
842 Entry
->Capabilities
= Capabilities
| EFI_MEMORY_RUNTIME
;
845 case GCD_ADD_IO_OPERATION
:
846 Entry
->GcdIoType
= GcdIoType
;
851 case GCD_FREE_MEMORY_OPERATION
:
852 case GCD_FREE_IO_OPERATION
:
853 Entry
->ImageHandle
= NULL
;
854 Entry
->DeviceHandle
= NULL
;
859 case GCD_REMOVE_MEMORY_OPERATION
:
860 Entry
->GcdMemoryType
= EfiGcdMemoryTypeNonExistent
;
861 Entry
->Capabilities
= 0;
863 case GCD_REMOVE_IO_OPERATION
:
864 Entry
->GcdIoType
= EfiGcdIoTypeNonExistent
;
867 // Set attribute operations
869 case GCD_SET_ATTRIBUTES_MEMORY_OPERATION
:
870 Entry
->Attributes
= Attributes
;
873 Link
= Link
->ForwardLink
;
879 Status
= CoreCleanupGcdMapEntry (TopEntry
, BottomEntry
, StartLink
, EndLink
, Map
);
882 DEBUG ((DEBUG_GCD
, " Status = %r\n", Status
));
884 if ((Operation
& GCD_MEMORY_SPACE_OPERATION
) != 0) {
885 CoreReleaseGcdMemoryLock ();
886 CoreDumpGcdMemorySpaceMap (FALSE
);
888 if ((Operation
& GCD_IO_SPACE_OPERATION
) != 0) {
889 CoreReleaseGcdIoLock ();
890 CoreDumpGcdIoSpaceMap (FALSE
);
898 Check whether an entry could be used to allocate space.
900 @param Operation Allocate memory or IO
901 @param Entry The entry to be tested
902 @param GcdMemoryType The desired memory type
903 @param GcdIoType The desired IO type
905 @retval EFI_NOT_FOUND The memory type does not match or there's an
906 image handle on the entry.
907 @retval EFI_UNSUPPORTED The operation unsupported.
908 @retval EFI_SUCCESS It's ok for this entry to be used to allocate
913 CoreAllocateSpaceCheckEntry (
915 IN EFI_GCD_MAP_ENTRY
*Entry
,
916 IN EFI_GCD_MEMORY_TYPE GcdMemoryType
,
917 IN EFI_GCD_IO_TYPE GcdIoType
920 if (Entry
->ImageHandle
!= NULL
) {
921 return EFI_NOT_FOUND
;
924 case GCD_ALLOCATE_MEMORY_OPERATION
:
925 if (Entry
->GcdMemoryType
!= GcdMemoryType
) {
926 return EFI_NOT_FOUND
;
929 case GCD_ALLOCATE_IO_OPERATION
:
930 if (Entry
->GcdIoType
!= GcdIoType
) {
931 return EFI_NOT_FOUND
;
935 return EFI_UNSUPPORTED
;
942 Allocate space on specified address and length.
944 @param Operation The type of operation (memory or IO)
945 @param GcdAllocateType The type of allocate operation
946 @param GcdMemoryType The desired memory type
947 @param GcdIoType The desired IO type
948 @param Alignment Align with 2^Alignment
949 @param Length Length to allocate
950 @param BaseAddress Base address to allocate
951 @param ImageHandle The image handle consume the allocated space.
952 @param DeviceHandle The device handle consume the allocated space.
954 @retval EFI_INVALID_PARAMETER Invalid parameter.
955 @retval EFI_NOT_FOUND No descriptor for the desired space exists.
956 @retval EFI_SUCCESS Space successfully allocated.
962 IN EFI_GCD_ALLOCATE_TYPE GcdAllocateType
,
963 IN EFI_GCD_MEMORY_TYPE GcdMemoryType
,
964 IN EFI_GCD_IO_TYPE GcdIoType
,
967 IN OUT EFI_PHYSICAL_ADDRESS
*BaseAddress
,
968 IN EFI_HANDLE ImageHandle
,
969 IN EFI_HANDLE DeviceHandle OPTIONAL
973 EFI_PHYSICAL_ADDRESS AlignmentMask
;
974 EFI_PHYSICAL_ADDRESS MaxAddress
;
978 EFI_GCD_MAP_ENTRY
*Entry
;
979 EFI_GCD_MAP_ENTRY
*TopEntry
;
980 EFI_GCD_MAP_ENTRY
*BottomEntry
;
981 LIST_ENTRY
*StartLink
;
986 // Make sure parameters are valid
988 if (GcdAllocateType
< 0 || GcdAllocateType
>= EfiGcdMaxAllocateType
) {
989 DEBUG ((DEBUG_GCD
, " Status = %r\n", EFI_INVALID_PARAMETER
));
990 return EFI_INVALID_PARAMETER
;
992 if (GcdMemoryType
< 0 || GcdMemoryType
>= EfiGcdMemoryTypeMaximum
) {
993 DEBUG ((DEBUG_GCD
, " Status = %r\n", EFI_INVALID_PARAMETER
));
994 return EFI_INVALID_PARAMETER
;
996 if (GcdIoType
< 0 || GcdIoType
>= EfiGcdIoTypeMaximum
) {
997 DEBUG ((DEBUG_GCD
, " Status = %r\n", EFI_INVALID_PARAMETER
));
998 return EFI_INVALID_PARAMETER
;
1000 if (BaseAddress
== NULL
) {
1001 DEBUG ((DEBUG_GCD
, " Status = %r\n", EFI_INVALID_PARAMETER
));
1002 return EFI_INVALID_PARAMETER
;
1004 if (ImageHandle
== NULL
) {
1005 DEBUG ((DEBUG_GCD
, " Status = %r\n", EFI_INVALID_PARAMETER
));
1006 return EFI_INVALID_PARAMETER
;
1008 if (Alignment
>= 64) {
1009 DEBUG ((DEBUG_GCD
, " Status = %r\n", EFI_NOT_FOUND
));
1010 return EFI_NOT_FOUND
;
1013 DEBUG ((DEBUG_GCD
, " Status = %r\n", EFI_INVALID_PARAMETER
));
1014 return EFI_INVALID_PARAMETER
;
1018 if ((Operation
& GCD_MEMORY_SPACE_OPERATION
) != 0) {
1019 CoreAcquireGcdMemoryLock ();
1020 Map
= &mGcdMemorySpaceMap
;
1021 } else if ((Operation
& GCD_IO_SPACE_OPERATION
) != 0) {
1022 CoreAcquireGcdIoLock ();
1023 Map
= &mGcdIoSpaceMap
;
1032 // Compute alignment bit mask
1034 AlignmentMask
= LShiftU64 (1, Alignment
) - 1;
1036 if (GcdAllocateType
== EfiGcdAllocateAddress
) {
1038 // Verify that the BaseAddress passed in is aligned correctly
1040 if ((*BaseAddress
& AlignmentMask
) != 0) {
1041 Status
= EFI_NOT_FOUND
;
1046 // Search for the list of descriptors that cover the range BaseAddress to BaseAddress+Length
1048 Status
= CoreSearchGcdMapEntry (*BaseAddress
, Length
, &StartLink
, &EndLink
, Map
);
1049 if (EFI_ERROR (Status
)) {
1050 Status
= EFI_NOT_FOUND
;
1053 ASSERT (StartLink
!= NULL
&& EndLink
!= NULL
);
1056 // Verify that the list of descriptors are unallocated memory matching GcdMemoryType.
1059 while (Link
!= EndLink
->ForwardLink
) {
1060 Entry
= CR (Link
, EFI_GCD_MAP_ENTRY
, Link
, EFI_GCD_MAP_SIGNATURE
);
1061 Link
= Link
->ForwardLink
;
1062 Status
= CoreAllocateSpaceCheckEntry (Operation
, Entry
, GcdMemoryType
, GcdIoType
);
1063 if (EFI_ERROR (Status
)) {
1070 Entry
= CR (Map
->BackLink
, EFI_GCD_MAP_ENTRY
, Link
, EFI_GCD_MAP_SIGNATURE
);
1073 // Compute the maximum address to use in the search algorithm
1075 if (GcdAllocateType
== EfiGcdAllocateMaxAddressSearchBottomUp
||
1076 GcdAllocateType
== EfiGcdAllocateMaxAddressSearchTopDown
) {
1077 MaxAddress
= *BaseAddress
;
1079 MaxAddress
= Entry
->EndAddress
;
1083 // Verify that the list of descriptors are unallocated memory matching GcdMemoryType.
1085 if (GcdAllocateType
== EfiGcdAllocateMaxAddressSearchTopDown
||
1086 GcdAllocateType
== EfiGcdAllocateAnySearchTopDown
) {
1087 Link
= Map
->BackLink
;
1089 Link
= Map
->ForwardLink
;
1091 while (Link
!= Map
) {
1092 Entry
= CR (Link
, EFI_GCD_MAP_ENTRY
, Link
, EFI_GCD_MAP_SIGNATURE
);
1094 if (GcdAllocateType
== EfiGcdAllocateMaxAddressSearchTopDown
||
1095 GcdAllocateType
== EfiGcdAllocateAnySearchTopDown
) {
1096 Link
= Link
->BackLink
;
1098 Link
= Link
->ForwardLink
;
1101 Status
= CoreAllocateSpaceCheckEntry (Operation
, Entry
, GcdMemoryType
, GcdIoType
);
1102 if (EFI_ERROR (Status
)) {
1106 if (GcdAllocateType
== EfiGcdAllocateMaxAddressSearchTopDown
||
1107 GcdAllocateType
== EfiGcdAllocateAnySearchTopDown
) {
1108 if ((Entry
->BaseAddress
+ Length
) > MaxAddress
) {
1111 if (Length
> (Entry
->EndAddress
+ 1)) {
1112 Status
= EFI_NOT_FOUND
;
1115 if (Entry
->EndAddress
> MaxAddress
) {
1116 *BaseAddress
= MaxAddress
;
1118 *BaseAddress
= Entry
->EndAddress
;
1120 *BaseAddress
= (*BaseAddress
+ 1 - Length
) & (~AlignmentMask
);
1122 *BaseAddress
= (Entry
->BaseAddress
+ AlignmentMask
) & (~AlignmentMask
);
1123 if ((*BaseAddress
+ Length
- 1) > MaxAddress
) {
1124 Status
= EFI_NOT_FOUND
;
1130 // Search for the list of descriptors that cover the range BaseAddress to BaseAddress+Length
1132 Status
= CoreSearchGcdMapEntry (*BaseAddress
, Length
, &StartLink
, &EndLink
, Map
);
1133 if (EFI_ERROR (Status
)) {
1134 Status
= EFI_NOT_FOUND
;
1137 ASSERT (StartLink
!= NULL
&& EndLink
!= NULL
);
1141 // Verify that the list of descriptors are unallocated memory matching GcdMemoryType.
1144 SubLink
= StartLink
;
1145 while (SubLink
!= EndLink
->ForwardLink
) {
1146 Entry
= CR (SubLink
, EFI_GCD_MAP_ENTRY
, Link
, EFI_GCD_MAP_SIGNATURE
);
1147 Status
= CoreAllocateSpaceCheckEntry (Operation
, Entry
, GcdMemoryType
, GcdIoType
);
1148 if (EFI_ERROR (Status
)) {
1153 SubLink
= SubLink
->ForwardLink
;
1161 Status
= EFI_NOT_FOUND
;
1166 // Allocate work space to perform this operation
1168 Status
= CoreAllocateGcdMapEntry (&TopEntry
, &BottomEntry
);
1169 if (EFI_ERROR (Status
)) {
1170 Status
= EFI_OUT_OF_RESOURCES
;
1173 ASSERT (TopEntry
!= NULL
&& BottomEntry
!= NULL
);
1176 // Convert/Insert the list of descriptors from StartLink to EndLink
1179 while (Link
!= EndLink
->ForwardLink
) {
1180 Entry
= CR (Link
, EFI_GCD_MAP_ENTRY
, Link
, EFI_GCD_MAP_SIGNATURE
);
1181 CoreInsertGcdMapEntry (Link
, Entry
, *BaseAddress
, Length
, TopEntry
, BottomEntry
);
1182 Entry
->ImageHandle
= ImageHandle
;
1183 Entry
->DeviceHandle
= DeviceHandle
;
1184 Link
= Link
->ForwardLink
;
1190 Status
= CoreCleanupGcdMapEntry (TopEntry
, BottomEntry
, StartLink
, EndLink
, Map
);
1193 DEBUG ((DEBUG_GCD
, " Status = %r", Status
));
1194 if (!EFI_ERROR (Status
)) {
1195 DEBUG ((DEBUG_GCD
, " (BaseAddress = %016lx)", *BaseAddress
));
1197 DEBUG ((DEBUG_GCD
, "\n"));
1199 if ((Operation
& GCD_MEMORY_SPACE_OPERATION
) != 0) {
1200 CoreReleaseGcdMemoryLock ();
1201 CoreDumpGcdMemorySpaceMap (FALSE
);
1203 if ((Operation
& GCD_IO_SPACE_OPERATION
) !=0) {
1204 CoreReleaseGcdIoLock ();
1205 CoreDumpGcdIoSpaceMap (FALSE
);
1213 Add a segment of memory to GCD map.
1215 @param GcdMemoryType Memory type of the segment.
1216 @param BaseAddress Base address of the segment.
1217 @param Length Length of the segment.
1218 @param Capabilities alterable attributes of the segment.
1220 @retval EFI_INVALID_PARAMETER Invalid parameters.
1221 @retval EFI_SUCCESS Successfully add a segment of memory space.
1225 CoreInternalAddMemorySpace (
1226 IN EFI_GCD_MEMORY_TYPE GcdMemoryType
,
1227 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
1229 IN UINT64 Capabilities
1232 DEBUG ((DEBUG_GCD
, "GCD:AddMemorySpace(Base=%016lx,Length=%016lx)\n", BaseAddress
, Length
));
1233 DEBUG ((DEBUG_GCD
, " GcdMemoryType = %a\n", mGcdMemoryTypeNames
[MIN (GcdMemoryType
, EfiGcdMemoryTypeMaximum
)]));
1234 DEBUG ((DEBUG_GCD
, " Capabilities = %016lx\n", Capabilities
));
1237 // Make sure parameters are valid
1239 if (GcdMemoryType
<= EfiGcdMemoryTypeNonExistent
|| GcdMemoryType
>= EfiGcdMemoryTypeMaximum
) {
1240 return EFI_INVALID_PARAMETER
;
1243 return CoreConvertSpace (GCD_ADD_MEMORY_OPERATION
, GcdMemoryType
, (EFI_GCD_IO_TYPE
) 0, BaseAddress
, Length
, Capabilities
, 0);
1247 // GCD Core Services
1251 Allocates nonexistent memory, reserved memory, system memory, or memorymapped
1252 I/O resources from the global coherency domain of the processor.
1254 @param GcdAllocateType The type of allocate operation
1255 @param GcdMemoryType The desired memory type
1256 @param Alignment Align with 2^Alignment
1257 @param Length Length to allocate
1258 @param BaseAddress Base address to allocate
1259 @param ImageHandle The image handle consume the allocated space.
1260 @param DeviceHandle The device handle consume the allocated space.
1262 @retval EFI_INVALID_PARAMETER Invalid parameter.
1263 @retval EFI_NOT_FOUND No descriptor contains the desired space.
1264 @retval EFI_SUCCESS Memory space successfully allocated.
1269 CoreAllocateMemorySpace (
1270 IN EFI_GCD_ALLOCATE_TYPE GcdAllocateType
,
1271 IN EFI_GCD_MEMORY_TYPE GcdMemoryType
,
1274 IN OUT EFI_PHYSICAL_ADDRESS
*BaseAddress
,
1275 IN EFI_HANDLE ImageHandle
,
1276 IN EFI_HANDLE DeviceHandle OPTIONAL
1279 DEBUG ((DEBUG_GCD
, "GCD:AllocateMemorySpace(Base=%016lx,Length=%016lx)\n", *BaseAddress
, Length
));
1280 DEBUG ((DEBUG_GCD
, " GcdAllocateType = %a\n", mGcdAllocationTypeNames
[MIN (GcdAllocateType
, EfiGcdMaxAllocateType
)]));
1281 DEBUG ((DEBUG_GCD
, " GcdMemoryType = %a\n", mGcdMemoryTypeNames
[MIN (GcdMemoryType
, EfiGcdMemoryTypeMaximum
)]));
1282 DEBUG ((DEBUG_GCD
, " Alignment = %016lx\n", LShiftU64 (1, Alignment
)));
1283 DEBUG ((DEBUG_GCD
, " ImageHandle = %p\n", ImageHandle
));
1284 DEBUG ((DEBUG_GCD
, " DeviceHandle = %p\n", DeviceHandle
));
1286 return CoreAllocateSpace (
1287 GCD_ALLOCATE_MEMORY_OPERATION
,
1290 (EFI_GCD_IO_TYPE
) 0,
1301 Adds reserved memory, system memory, or memory-mapped I/O resources to the
1302 global coherency domain of the processor.
1304 @param GcdMemoryType Memory type of the memory space.
1305 @param BaseAddress Base address of the memory space.
1306 @param Length Length of the memory space.
1307 @param Capabilities alterable attributes of the memory space.
1309 @retval EFI_SUCCESS Merged this memory space into GCD map.
1314 CoreAddMemorySpace (
1315 IN EFI_GCD_MEMORY_TYPE GcdMemoryType
,
1316 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
1318 IN UINT64 Capabilities
1322 EFI_PHYSICAL_ADDRESS PageBaseAddress
;
1325 Status
= CoreInternalAddMemorySpace (GcdMemoryType
, BaseAddress
, Length
, Capabilities
);
1327 if (!EFI_ERROR (Status
) && GcdMemoryType
== EfiGcdMemoryTypeSystemMemory
) {
1329 PageBaseAddress
= PageAlignLength (BaseAddress
);
1330 PageLength
= PageAlignLength (BaseAddress
+ Length
- PageBaseAddress
);
1332 Status
= CoreAllocateMemorySpace (
1333 EfiGcdAllocateAddress
,
1338 gDxeCoreImageHandle
,
1342 if (!EFI_ERROR (Status
)) {
1343 CoreAddMemoryDescriptor (
1344 EfiConventionalMemory
,
1346 RShiftU64 (PageLength
, EFI_PAGE_SHIFT
),
1350 for (; PageLength
!= 0; PageLength
-= EFI_PAGE_SIZE
, PageBaseAddress
+= EFI_PAGE_SIZE
) {
1351 Status
= CoreAllocateMemorySpace (
1352 EfiGcdAllocateAddress
,
1357 gDxeCoreImageHandle
,
1361 if (!EFI_ERROR (Status
)) {
1362 CoreAddMemoryDescriptor (
1363 EfiConventionalMemory
,
1377 Frees nonexistent memory, reserved memory, system memory, or memory-mapped
1378 I/O resources from the global coherency domain of the processor.
1380 @param BaseAddress Base address of the memory space.
1381 @param Length Length of the memory space.
1383 @retval EFI_SUCCESS Space successfully freed.
1388 CoreFreeMemorySpace (
1389 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
1393 DEBUG ((DEBUG_GCD
, "GCD:FreeMemorySpace(Base=%016lx,Length=%016lx)\n", BaseAddress
, Length
));
1395 return CoreConvertSpace (GCD_FREE_MEMORY_OPERATION
, (EFI_GCD_MEMORY_TYPE
) 0, (EFI_GCD_IO_TYPE
) 0, BaseAddress
, Length
, 0, 0);
1400 Removes reserved memory, system memory, or memory-mapped I/O resources from
1401 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 Successfully remove a segment of memory space.
1411 CoreRemoveMemorySpace (
1412 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
1416 DEBUG ((DEBUG_GCD
, "GCD:RemoveMemorySpace(Base=%016lx,Length=%016lx)\n", BaseAddress
, Length
));
1418 return CoreConvertSpace (GCD_REMOVE_MEMORY_OPERATION
, (EFI_GCD_MEMORY_TYPE
) 0, (EFI_GCD_IO_TYPE
) 0, BaseAddress
, Length
, 0, 0);
1423 Build a memory descriptor according to an entry.
1425 @param Descriptor The descriptor to be built
1426 @param Entry According to this entry
1430 BuildMemoryDescriptor (
1431 IN OUT EFI_GCD_MEMORY_SPACE_DESCRIPTOR
*Descriptor
,
1432 IN EFI_GCD_MAP_ENTRY
*Entry
1435 Descriptor
->BaseAddress
= Entry
->BaseAddress
;
1436 Descriptor
->Length
= Entry
->EndAddress
- Entry
->BaseAddress
+ 1;
1437 Descriptor
->Capabilities
= Entry
->Capabilities
;
1438 Descriptor
->Attributes
= Entry
->Attributes
;
1439 Descriptor
->GcdMemoryType
= Entry
->GcdMemoryType
;
1440 Descriptor
->ImageHandle
= Entry
->ImageHandle
;
1441 Descriptor
->DeviceHandle
= Entry
->DeviceHandle
;
1446 Retrieves the descriptor for a memory region containing a specified address.
1448 @param BaseAddress Specified start address
1449 @param Descriptor Specified length
1451 @retval EFI_INVALID_PARAMETER Invalid parameter
1452 @retval EFI_SUCCESS Successfully get memory space descriptor.
1457 CoreGetMemorySpaceDescriptor (
1458 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
1459 OUT EFI_GCD_MEMORY_SPACE_DESCRIPTOR
*Descriptor
1463 LIST_ENTRY
*StartLink
;
1464 LIST_ENTRY
*EndLink
;
1465 EFI_GCD_MAP_ENTRY
*Entry
;
1468 // Make sure parameters are valid
1470 if (Descriptor
== NULL
) {
1471 return EFI_INVALID_PARAMETER
;
1474 CoreAcquireGcdMemoryLock ();
1477 // Search for the list of descriptors that contain BaseAddress
1479 Status
= CoreSearchGcdMapEntry (BaseAddress
, 1, &StartLink
, &EndLink
, &mGcdMemorySpaceMap
);
1480 if (EFI_ERROR (Status
)) {
1481 Status
= EFI_NOT_FOUND
;
1483 ASSERT (StartLink
!= NULL
&& EndLink
!= NULL
);
1485 // Copy the contents of the found descriptor into Descriptor
1487 Entry
= CR (StartLink
, EFI_GCD_MAP_ENTRY
, Link
, EFI_GCD_MAP_SIGNATURE
);
1488 BuildMemoryDescriptor (Descriptor
, Entry
);
1491 CoreReleaseGcdMemoryLock ();
1498 Modifies the attributes for a memory region in the global coherency domain of the
1501 @param BaseAddress Specified start address
1502 @param Length Specified length
1503 @param Attributes Specified attributes
1505 @retval EFI_SUCCESS Successfully set attribute of a segment of
1511 CoreSetMemorySpaceAttributes (
1512 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
1514 IN UINT64 Attributes
1517 DEBUG ((DEBUG_GCD
, "GCD:SetMemorySpaceAttributes(Base=%016lx,Length=%016lx)\n", BaseAddress
, Length
));
1518 DEBUG ((DEBUG_GCD
, " Attributes = %016lx\n", Attributes
));
1520 return CoreConvertSpace (GCD_SET_ATTRIBUTES_MEMORY_OPERATION
, (EFI_GCD_MEMORY_TYPE
) 0, (EFI_GCD_IO_TYPE
) 0, BaseAddress
, Length
, 0, Attributes
);
1525 Returns a map of the memory resources in the global coherency domain of the
1528 @param NumberOfDescriptors Number of descriptors.
1529 @param MemorySpaceMap Descriptor array
1531 @retval EFI_INVALID_PARAMETER Invalid parameter
1532 @retval EFI_OUT_OF_RESOURCES No enough buffer to allocate
1533 @retval EFI_SUCCESS Successfully get memory space map.
1538 CoreGetMemorySpaceMap (
1539 OUT UINTN
*NumberOfDescriptors
,
1540 OUT EFI_GCD_MEMORY_SPACE_DESCRIPTOR
**MemorySpaceMap
1545 EFI_GCD_MAP_ENTRY
*Entry
;
1546 EFI_GCD_MEMORY_SPACE_DESCRIPTOR
*Descriptor
;
1549 // Make sure parameters are valid
1551 if (NumberOfDescriptors
== NULL
) {
1552 return EFI_INVALID_PARAMETER
;
1554 if (MemorySpaceMap
== NULL
) {
1555 return EFI_INVALID_PARAMETER
;
1558 CoreAcquireGcdMemoryLock ();
1561 // Count the number of descriptors
1563 *NumberOfDescriptors
= CoreCountGcdMapEntry (&mGcdMemorySpaceMap
);
1566 // Allocate the MemorySpaceMap
1568 *MemorySpaceMap
= AllocatePool (*NumberOfDescriptors
* sizeof (EFI_GCD_MEMORY_SPACE_DESCRIPTOR
));
1569 if (*MemorySpaceMap
== NULL
) {
1570 Status
= EFI_OUT_OF_RESOURCES
;
1575 // Fill in the MemorySpaceMap
1577 Descriptor
= *MemorySpaceMap
;
1578 Link
= mGcdMemorySpaceMap
.ForwardLink
;
1579 while (Link
!= &mGcdMemorySpaceMap
) {
1580 Entry
= CR (Link
, EFI_GCD_MAP_ENTRY
, Link
, EFI_GCD_MAP_SIGNATURE
);
1581 BuildMemoryDescriptor (Descriptor
, Entry
);
1583 Link
= Link
->ForwardLink
;
1585 Status
= EFI_SUCCESS
;
1588 CoreReleaseGcdMemoryLock ();
1594 Adds reserved I/O or I/O resources to the global coherency domain of the processor.
1596 @param GcdIoType IO type of the segment.
1597 @param BaseAddress Base address of the segment.
1598 @param Length Length of the segment.
1600 @retval EFI_SUCCESS Merged this segment into GCD map.
1601 @retval EFI_INVALID_PARAMETER Parameter not valid
1607 IN EFI_GCD_IO_TYPE GcdIoType
,
1608 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
1612 DEBUG ((DEBUG_GCD
, "GCD:AddIoSpace(Base=%016lx,Length=%016lx)\n", BaseAddress
, Length
));
1613 DEBUG ((DEBUG_GCD
, " GcdIoType = %a\n", mGcdIoTypeNames
[MIN (GcdIoType
, EfiGcdIoTypeMaximum
)]));
1616 // Make sure parameters are valid
1618 if (GcdIoType
<= EfiGcdIoTypeNonExistent
|| GcdIoType
>= EfiGcdIoTypeMaximum
) {
1619 return EFI_INVALID_PARAMETER
;
1621 return CoreConvertSpace (GCD_ADD_IO_OPERATION
, (EFI_GCD_MEMORY_TYPE
) 0, GcdIoType
, BaseAddress
, Length
, 0, 0);
1626 Allocates nonexistent I/O, reserved I/O, or I/O resources from the global coherency
1627 domain of the processor.
1629 @param GcdAllocateType The type of allocate operation
1630 @param GcdIoType The desired IO type
1631 @param Alignment Align with 2^Alignment
1632 @param Length Length to allocate
1633 @param BaseAddress Base address to allocate
1634 @param ImageHandle The image handle consume the allocated space.
1635 @param DeviceHandle The device handle consume the allocated space.
1637 @retval EFI_INVALID_PARAMETER Invalid parameter.
1638 @retval EFI_NOT_FOUND No descriptor contains the desired space.
1639 @retval EFI_SUCCESS IO space successfully allocated.
1644 CoreAllocateIoSpace (
1645 IN EFI_GCD_ALLOCATE_TYPE GcdAllocateType
,
1646 IN EFI_GCD_IO_TYPE GcdIoType
,
1649 IN OUT EFI_PHYSICAL_ADDRESS
*BaseAddress
,
1650 IN EFI_HANDLE ImageHandle
,
1651 IN EFI_HANDLE DeviceHandle OPTIONAL
1654 DEBUG ((DEBUG_GCD
, "GCD:AllocateIoSpace(Base=%016lx,Length=%016lx)\n", *BaseAddress
, Length
));
1655 DEBUG ((DEBUG_GCD
, " GcdAllocateType = %a\n", mGcdAllocationTypeNames
[MIN (GcdAllocateType
, EfiGcdMaxAllocateType
)]));
1656 DEBUG ((DEBUG_GCD
, " GcdIoType = %a\n", mGcdIoTypeNames
[MIN (GcdIoType
, EfiGcdIoTypeMaximum
)]));
1657 DEBUG ((DEBUG_GCD
, " Alignment = %016lx\n", LShiftU64 (1, Alignment
)));
1658 DEBUG ((DEBUG_GCD
, " ImageHandle = %p\n", ImageHandle
));
1659 DEBUG ((DEBUG_GCD
, " DeviceHandle = %p\n", DeviceHandle
));
1661 return CoreAllocateSpace (
1662 GCD_ALLOCATE_IO_OPERATION
,
1664 (EFI_GCD_MEMORY_TYPE
) 0,
1676 Frees nonexistent I/O, reserved I/O, or I/O resources from the global coherency
1677 domain of the processor.
1679 @param BaseAddress Base address of the segment.
1680 @param Length Length of the segment.
1682 @retval EFI_SUCCESS Space successfully freed.
1688 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
1692 DEBUG ((DEBUG_GCD
, "GCD:FreeIoSpace(Base=%016lx,Length=%016lx)\n", BaseAddress
, Length
));
1694 return CoreConvertSpace (GCD_FREE_IO_OPERATION
, (EFI_GCD_MEMORY_TYPE
) 0, (EFI_GCD_IO_TYPE
) 0, BaseAddress
, Length
, 0, 0);
1699 Removes reserved I/O or I/O resources from the global coherency domain of the
1702 @param BaseAddress Base address of the segment.
1703 @param Length Length of the segment.
1705 @retval EFI_SUCCESS Successfully removed a segment of IO space.
1711 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
1715 DEBUG ((DEBUG_GCD
, "GCD:RemoveIoSpace(Base=%016lx,Length=%016lx)\n", BaseAddress
, Length
));
1717 return CoreConvertSpace (GCD_REMOVE_IO_OPERATION
, (EFI_GCD_MEMORY_TYPE
) 0, (EFI_GCD_IO_TYPE
) 0, BaseAddress
, Length
, 0, 0);
1722 Build a IO descriptor according to an entry.
1724 @param Descriptor The descriptor to be built
1725 @param Entry According to this entry
1730 IN EFI_GCD_IO_SPACE_DESCRIPTOR
*Descriptor
,
1731 IN EFI_GCD_MAP_ENTRY
*Entry
1734 Descriptor
->BaseAddress
= Entry
->BaseAddress
;
1735 Descriptor
->Length
= Entry
->EndAddress
- Entry
->BaseAddress
+ 1;
1736 Descriptor
->GcdIoType
= Entry
->GcdIoType
;
1737 Descriptor
->ImageHandle
= Entry
->ImageHandle
;
1738 Descriptor
->DeviceHandle
= Entry
->DeviceHandle
;
1743 Retrieves the descriptor for an I/O region containing a specified address.
1745 @param BaseAddress Specified start address
1746 @param Descriptor Specified length
1748 @retval EFI_INVALID_PARAMETER Descriptor is NULL.
1749 @retval EFI_SUCCESS Successfully get the IO space descriptor.
1754 CoreGetIoSpaceDescriptor (
1755 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
1756 OUT EFI_GCD_IO_SPACE_DESCRIPTOR
*Descriptor
1760 LIST_ENTRY
*StartLink
;
1761 LIST_ENTRY
*EndLink
;
1762 EFI_GCD_MAP_ENTRY
*Entry
;
1765 // Make sure parameters are valid
1767 if (Descriptor
== NULL
) {
1768 return EFI_INVALID_PARAMETER
;
1771 CoreAcquireGcdIoLock ();
1774 // Search for the list of descriptors that contain BaseAddress
1776 Status
= CoreSearchGcdMapEntry (BaseAddress
, 1, &StartLink
, &EndLink
, &mGcdIoSpaceMap
);
1777 if (EFI_ERROR (Status
)) {
1778 Status
= EFI_NOT_FOUND
;
1780 ASSERT (StartLink
!= NULL
&& EndLink
!= NULL
);
1782 // Copy the contents of the found descriptor into Descriptor
1784 Entry
= CR (StartLink
, EFI_GCD_MAP_ENTRY
, Link
, EFI_GCD_MAP_SIGNATURE
);
1785 BuildIoDescriptor (Descriptor
, Entry
);
1788 CoreReleaseGcdIoLock ();
1795 Returns a map of the I/O resources in the global coherency domain of the processor.
1797 @param NumberOfDescriptors Number of descriptors.
1798 @param IoSpaceMap Descriptor array
1800 @retval EFI_INVALID_PARAMETER Invalid parameter
1801 @retval EFI_OUT_OF_RESOURCES No enough buffer to allocate
1802 @retval EFI_SUCCESS Successfully get IO space map.
1808 OUT UINTN
*NumberOfDescriptors
,
1809 OUT EFI_GCD_IO_SPACE_DESCRIPTOR
**IoSpaceMap
1814 EFI_GCD_MAP_ENTRY
*Entry
;
1815 EFI_GCD_IO_SPACE_DESCRIPTOR
*Descriptor
;
1818 // Make sure parameters are valid
1820 if (NumberOfDescriptors
== NULL
) {
1821 return EFI_INVALID_PARAMETER
;
1823 if (IoSpaceMap
== NULL
) {
1824 return EFI_INVALID_PARAMETER
;
1827 CoreAcquireGcdIoLock ();
1830 // Count the number of descriptors
1832 *NumberOfDescriptors
= CoreCountGcdMapEntry (&mGcdIoSpaceMap
);
1835 // Allocate the IoSpaceMap
1837 *IoSpaceMap
= AllocatePool (*NumberOfDescriptors
* sizeof (EFI_GCD_IO_SPACE_DESCRIPTOR
));
1838 if (*IoSpaceMap
== NULL
) {
1839 Status
= EFI_OUT_OF_RESOURCES
;
1844 // Fill in the IoSpaceMap
1846 Descriptor
= *IoSpaceMap
;
1847 Link
= mGcdIoSpaceMap
.ForwardLink
;
1848 while (Link
!= &mGcdIoSpaceMap
) {
1849 Entry
= CR (Link
, EFI_GCD_MAP_ENTRY
, Link
, EFI_GCD_MAP_SIGNATURE
);
1850 BuildIoDescriptor (Descriptor
, Entry
);
1852 Link
= Link
->ForwardLink
;
1854 Status
= EFI_SUCCESS
;
1857 CoreReleaseGcdIoLock ();
1863 Converts a Resource Descriptor HOB attributes mask to an EFI Memory Descriptor
1866 @param GcdMemoryType Type of resource in the GCD memory map.
1867 @param Attributes The attribute mask in the Resource Descriptor
1870 @return The capabilities mask for an EFI Memory Descriptor.
1874 CoreConvertResourceDescriptorHobAttributesToCapabilities (
1875 EFI_GCD_MEMORY_TYPE GcdMemoryType
,
1879 UINT64 Capabilities
;
1880 GCD_ATTRIBUTE_CONVERSION_ENTRY
*Conversion
;
1883 // Convert the Resource HOB Attributes to an EFI Memory Capabilities mask
1885 for (Capabilities
= 0, Conversion
= mAttributeConversionTable
; Conversion
->Attribute
!= 0; Conversion
++) {
1886 if (Conversion
->Memory
|| (GcdMemoryType
!= EfiGcdMemoryTypeSystemMemory
)) {
1887 if (Attributes
& Conversion
->Attribute
) {
1888 Capabilities
|= Conversion
->Capability
;
1893 return Capabilities
;
1898 External function. Initializes memory services based on the memory
1899 descriptor HOBs. This function is responsible for priming the memory
1900 map, so memory allocations and resource allocations can be made.
1901 The first part of this function can not depend on any memory services
1902 until at least one memory descriptor is provided to the memory services.
1904 @param HobStart The start address of the HOB.
1905 @param MemoryBaseAddress Start address of memory region found to init DXE
1907 @param MemoryLength Length of memory region found to init DXE core.
1909 @retval EFI_SUCCESS Memory services successfully initialized.
1913 CoreInitializeMemoryServices (
1915 OUT EFI_PHYSICAL_ADDRESS
*MemoryBaseAddress
,
1916 OUT UINT64
*MemoryLength
1919 EFI_PEI_HOB_POINTERS Hob
;
1920 EFI_MEMORY_TYPE_INFORMATION
*EfiMemoryTypeInformation
;
1923 EFI_HOB_HANDOFF_INFO_TABLE
*PhitHob
;
1924 EFI_HOB_RESOURCE_DESCRIPTOR
*ResourceHob
;
1925 EFI_HOB_RESOURCE_DESCRIPTOR
*PhitResourceHob
;
1926 EFI_PHYSICAL_ADDRESS BaseAddress
;
1929 UINT64 Capabilities
;
1930 EFI_PHYSICAL_ADDRESS MaxMemoryBaseAddress
;
1931 UINT64 MaxMemoryLength
;
1932 UINT64 MaxMemoryAttributes
;
1933 EFI_PHYSICAL_ADDRESS MaxAddress
;
1934 EFI_PHYSICAL_ADDRESS HighAddress
;
1935 EFI_HOB_RESOURCE_DESCRIPTOR
*MaxResourceHob
;
1936 EFI_HOB_GUID_TYPE
*GuidHob
;
1937 UINT32 ReservedCodePageNumber
;
1940 // Point at the first HOB. This must be the PHIT HOB.
1942 Hob
.Raw
= *HobStart
;
1943 ASSERT (GET_HOB_TYPE (Hob
) == EFI_HOB_TYPE_HANDOFF
);
1946 // Initialize the spin locks and maps in the memory services.
1947 // Also fill in the memory services into the EFI Boot Services Table
1949 CoreInitializePool ();
1952 // Initialize Local Variables
1954 PhitResourceHob
= NULL
;
1955 MaxResourceHob
= NULL
;
1960 MaxMemoryBaseAddress
= 0;
1961 MaxMemoryLength
= 0;
1962 MaxMemoryAttributes
= 0;
1965 // Cache the PHIT HOB for later use
1967 PhitHob
= Hob
.HandoffInformationTable
;
1969 if (PcdGet64(PcdLoadModuleAtFixAddressEnable
) != 0) {
1970 ReservedCodePageNumber
= PcdGet32(PcdLoadFixAddressRuntimeCodePageNumber
);
1971 ReservedCodePageNumber
+= PcdGet32(PcdLoadFixAddressBootTimeCodePageNumber
);
1974 // cache the Top address for loading modules at Fixed Address
1976 gLoadModuleAtFixAddressConfigurationTable
.DxeCodeTopAddress
= PhitHob
->EfiMemoryTop
1977 + EFI_PAGES_TO_SIZE(ReservedCodePageNumber
);
1980 // See if a Memory Type Information HOB is available
1982 GuidHob
= GetFirstGuidHob (&gEfiMemoryTypeInformationGuid
);
1983 if (GuidHob
!= NULL
) {
1984 EfiMemoryTypeInformation
= GET_GUID_HOB_DATA (GuidHob
);
1985 DataSize
= GET_GUID_HOB_DATA_SIZE (GuidHob
);
1986 if (EfiMemoryTypeInformation
!= NULL
&& DataSize
> 0 && DataSize
<= (EfiMaxMemoryType
+ 1) * sizeof (EFI_MEMORY_TYPE_INFORMATION
)) {
1987 CopyMem (&gMemoryTypeInformation
, EfiMemoryTypeInformation
, DataSize
);
1992 // Find the Resource Descriptor HOB that contains range FreeMemoryBaseAddress..FreeMemoryLength
1996 for (Hob
.Raw
= *HobStart
; !END_OF_HOB_LIST(Hob
); Hob
.Raw
= GET_NEXT_HOB(Hob
)) {
1998 if (GET_HOB_TYPE (Hob
) == EFI_HOB_TYPE_RESOURCE_DESCRIPTOR
) {
2000 ResourceHob
= Hob
.ResourceDescriptor
;
2002 if (ResourceHob
->ResourceType
== EFI_RESOURCE_SYSTEM_MEMORY
&&
2003 (ResourceHob
->ResourceAttribute
& MEMORY_ATTRIBUTE_MASK
) == TESTED_MEMORY_ATTRIBUTES
) {
2005 if (PhitHob
->EfiFreeMemoryBottom
>= ResourceHob
->PhysicalStart
&&
2006 PhitHob
->EfiFreeMemoryTop
<= (ResourceHob
->PhysicalStart
+ ResourceHob
->ResourceLength
) ) {
2009 // Cache the resource descriptor HOB for the memory region described by the PHIT HOB
2011 PhitResourceHob
= ResourceHob
;
2014 Attributes
= PhitResourceHob
->ResourceAttribute
;
2015 BaseAddress
= PageAlignAddress (PhitHob
->EfiMemoryTop
);
2016 Length
= PageAlignLength (ResourceHob
->PhysicalStart
+ ResourceHob
->ResourceLength
- BaseAddress
);
2017 if (Length
< MINIMUM_INITIAL_MEMORY_SIZE
) {
2018 BaseAddress
= PageAlignAddress (PhitHob
->EfiFreeMemoryBottom
);
2019 Length
= PageAlignLength (PhitHob
->EfiFreeMemoryTop
- BaseAddress
);
2020 if (Length
< MINIMUM_INITIAL_MEMORY_SIZE
) {
2021 BaseAddress
= PageAlignAddress (ResourceHob
->PhysicalStart
);
2022 Length
= PageAlignLength ((UINT64
)((UINTN
)*HobStart
- BaseAddress
));
2032 // Assert if a resource descriptor HOB for the memory region described by the PHIT was not found
2037 // Search all the resource descriptor HOBs from the highest possible addresses down for a memory
2038 // region that is big enough to initialize the DXE core. Always skip the PHIT Resource HOB.
2039 // The max address must be within the physically addressible range for the processor.
2041 MaxMemoryLength
= 0;
2042 MaxAddress
= MAX_ADDRESS
;
2047 // Search for a tested memory region that is below MaxAddress
2049 for (Hob
.Raw
= *HobStart
; !END_OF_HOB_LIST(Hob
); Hob
.Raw
= GET_NEXT_HOB(Hob
)) {
2052 // See if this is a resource descriptor HOB that does not contain the PHIT.
2054 if (Hob
.ResourceDescriptor
!= PhitResourceHob
&& GET_HOB_TYPE (Hob
) == EFI_HOB_TYPE_RESOURCE_DESCRIPTOR
) {
2056 ResourceHob
= Hob
.ResourceDescriptor
;
2058 // See if this resource descrior HOB describes tested system memory below MaxAddress
2060 if (ResourceHob
->ResourceType
== EFI_RESOURCE_SYSTEM_MEMORY
&&
2061 (ResourceHob
->ResourceAttribute
& MEMORY_ATTRIBUTE_MASK
) == TESTED_MEMORY_ATTRIBUTES
&&
2062 ResourceHob
->PhysicalStart
+ ResourceHob
->ResourceLength
<= MaxAddress
) {
2064 // See if this is the highest tested system memory region below MaxAddress
2066 if (ResourceHob
->PhysicalStart
> HighAddress
) {
2068 MaxResourceHob
= ResourceHob
;
2069 HighAddress
= MaxResourceHob
->PhysicalStart
;
2077 // Compute the size of the tested memory region below MaxAddrees
2079 MaxMemoryBaseAddress
= PageAlignAddress (MaxResourceHob
->PhysicalStart
);
2080 MaxMemoryLength
= PageAlignLength (MaxResourceHob
->PhysicalStart
+ MaxResourceHob
->ResourceLength
- MaxMemoryBaseAddress
);
2081 MaxMemoryAttributes
= MaxResourceHob
->ResourceAttribute
;
2083 MaxAddress
= ResourceHob
->PhysicalStart
;
2084 } while (Found
&& MaxMemoryLength
< MINIMUM_INITIAL_MEMORY_SIZE
);
2086 if ((Length
< MINIMUM_INITIAL_MEMORY_SIZE
) ||
2087 (MaxMemoryBaseAddress
> BaseAddress
&& MaxMemoryLength
>= MINIMUM_INITIAL_MEMORY_SIZE
)) {
2088 BaseAddress
= MaxMemoryBaseAddress
;
2089 Length
= MaxMemoryLength
;
2090 Attributes
= MaxMemoryAttributes
;
2094 // If no memory regions are found that are big enough to initialize the DXE core, then ASSERT().
2096 ASSERT (Length
>= MINIMUM_INITIAL_MEMORY_SIZE
);
2099 // Convert the Resource HOB Attributes to an EFI Memory Capabilities mask
2101 Capabilities
= CoreConvertResourceDescriptorHobAttributesToCapabilities (EfiGcdMemoryTypeSystemMemory
, Attributes
);
2104 // Declare the very first memory region, so the EFI Memory Services are available.
2106 CoreAddMemoryDescriptor (
2107 EfiConventionalMemory
,
2109 RShiftU64 (Length
, EFI_PAGE_SHIFT
),
2113 *MemoryBaseAddress
= BaseAddress
;
2114 *MemoryLength
= Length
;
2121 External function. Initializes the GCD and memory services based on the memory
2122 descriptor HOBs. This function is responsible for priming the GCD map and the
2123 memory map, so memory allocations and resource allocations can be made. The
2124 HobStart will be relocated to a pool buffer.
2126 @param HobStart The start address of the HOB
2127 @param MemoryBaseAddress Start address of memory region found to init DXE
2129 @param MemoryLength Length of memory region found to init DXE core.
2131 @retval EFI_SUCCESS GCD services successfully initialized.
2135 CoreInitializeGcdServices (
2136 IN OUT VOID
**HobStart
,
2137 IN EFI_PHYSICAL_ADDRESS MemoryBaseAddress
,
2138 IN UINT64 MemoryLength
2141 EFI_PEI_HOB_POINTERS Hob
;
2143 EFI_HOB_HANDOFF_INFO_TABLE
*PhitHob
;
2144 UINT8 SizeOfMemorySpace
;
2145 UINT8 SizeOfIoSpace
;
2146 EFI_HOB_RESOURCE_DESCRIPTOR
*ResourceHob
;
2147 EFI_PHYSICAL_ADDRESS BaseAddress
;
2150 EFI_GCD_MAP_ENTRY
*Entry
;
2151 EFI_GCD_MEMORY_TYPE GcdMemoryType
;
2152 EFI_GCD_IO_TYPE GcdIoType
;
2153 EFI_GCD_MEMORY_SPACE_DESCRIPTOR Descriptor
;
2154 EFI_HOB_MEMORY_ALLOCATION
*MemoryHob
;
2155 EFI_HOB_FIRMWARE_VOLUME
*FirmwareVolumeHob
;
2156 UINTN NumberOfDescriptors
;
2157 EFI_GCD_MEMORY_SPACE_DESCRIPTOR
*MemorySpaceMap
;
2159 UINT64 Capabilities
;
2160 EFI_HOB_CPU
* CpuHob
;
2163 // Cache the PHIT HOB for later use
2165 PhitHob
= (EFI_HOB_HANDOFF_INFO_TABLE
*)(*HobStart
);
2168 // Get the number of address lines in the I/O and Memory space for the CPU
2170 CpuHob
= GetFirstHob (EFI_HOB_TYPE_CPU
);
2171 ASSERT (CpuHob
!= NULL
);
2172 SizeOfMemorySpace
= CpuHob
->SizeOfMemorySpace
;
2173 SizeOfIoSpace
= CpuHob
->SizeOfIoSpace
;
2176 // Initialize the GCD Memory Space Map
2178 Entry
= AllocateCopyPool (sizeof (EFI_GCD_MAP_ENTRY
), &mGcdMemorySpaceMapEntryTemplate
);
2179 ASSERT (Entry
!= NULL
);
2181 Entry
->EndAddress
= LShiftU64 (1, SizeOfMemorySpace
) - 1;
2183 InsertHeadList (&mGcdMemorySpaceMap
, &Entry
->Link
);
2185 CoreDumpGcdMemorySpaceMap (TRUE
);
2188 // Initialize the GCD I/O Space Map
2190 Entry
= AllocateCopyPool (sizeof (EFI_GCD_MAP_ENTRY
), &mGcdIoSpaceMapEntryTemplate
);
2191 ASSERT (Entry
!= NULL
);
2193 Entry
->EndAddress
= LShiftU64 (1, SizeOfIoSpace
) - 1;
2195 InsertHeadList (&mGcdIoSpaceMap
, &Entry
->Link
);
2197 CoreDumpGcdIoSpaceMap (TRUE
);
2200 // Walk the HOB list and add all resource descriptors to the GCD
2202 for (Hob
.Raw
= *HobStart
; !END_OF_HOB_LIST(Hob
); Hob
.Raw
= GET_NEXT_HOB(Hob
)) {
2204 GcdMemoryType
= EfiGcdMemoryTypeNonExistent
;
2205 GcdIoType
= EfiGcdIoTypeNonExistent
;
2207 if (GET_HOB_TYPE (Hob
) == EFI_HOB_TYPE_RESOURCE_DESCRIPTOR
) {
2209 ResourceHob
= Hob
.ResourceDescriptor
;
2211 switch (ResourceHob
->ResourceType
) {
2212 case EFI_RESOURCE_SYSTEM_MEMORY
:
2213 if ((ResourceHob
->ResourceAttribute
& MEMORY_ATTRIBUTE_MASK
) == TESTED_MEMORY_ATTRIBUTES
) {
2214 GcdMemoryType
= EfiGcdMemoryTypeSystemMemory
;
2216 if ((ResourceHob
->ResourceAttribute
& MEMORY_ATTRIBUTE_MASK
) == INITIALIZED_MEMORY_ATTRIBUTES
) {
2217 GcdMemoryType
= EfiGcdMemoryTypeReserved
;
2219 if ((ResourceHob
->ResourceAttribute
& MEMORY_ATTRIBUTE_MASK
) == PRESENT_MEMORY_ATTRIBUTES
) {
2220 GcdMemoryType
= EfiGcdMemoryTypeReserved
;
2223 case EFI_RESOURCE_MEMORY_MAPPED_IO
:
2224 case EFI_RESOURCE_FIRMWARE_DEVICE
:
2225 GcdMemoryType
= EfiGcdMemoryTypeMemoryMappedIo
;
2227 case EFI_RESOURCE_MEMORY_MAPPED_IO_PORT
:
2228 case EFI_RESOURCE_MEMORY_RESERVED
:
2229 GcdMemoryType
= EfiGcdMemoryTypeReserved
;
2231 case EFI_RESOURCE_IO
:
2232 GcdIoType
= EfiGcdIoTypeIo
;
2234 case EFI_RESOURCE_IO_RESERVED
:
2235 GcdIoType
= EfiGcdIoTypeReserved
;
2239 if (GcdMemoryType
!= EfiGcdMemoryTypeNonExistent
) {
2241 // Convert the Resource HOB Attributes to an EFI Memory Capabilities mask
2243 Capabilities
= CoreConvertResourceDescriptorHobAttributesToCapabilities (
2245 ResourceHob
->ResourceAttribute
2248 Status
= CoreInternalAddMemorySpace (
2250 ResourceHob
->PhysicalStart
,
2251 ResourceHob
->ResourceLength
,
2256 if (GcdIoType
!= EfiGcdIoTypeNonExistent
) {
2257 Status
= CoreAddIoSpace (
2259 ResourceHob
->PhysicalStart
,
2260 ResourceHob
->ResourceLength
2267 // Allocate first memory region from the GCD by the DXE core
2269 Status
= CoreAllocateMemorySpace (
2270 EfiGcdAllocateAddress
,
2271 EfiGcdMemoryTypeSystemMemory
,
2275 gDxeCoreImageHandle
,
2280 // Walk the HOB list and allocate all memory space that is consumed by memory allocation HOBs,
2281 // and Firmware Volume HOBs. Also update the EFI Memory Map with the memory allocation HOBs.
2283 for (Hob
.Raw
= *HobStart
; !END_OF_HOB_LIST(Hob
); Hob
.Raw
= GET_NEXT_HOB(Hob
)) {
2284 if (GET_HOB_TYPE (Hob
) == EFI_HOB_TYPE_MEMORY_ALLOCATION
) {
2285 MemoryHob
= Hob
.MemoryAllocation
;
2286 BaseAddress
= MemoryHob
->AllocDescriptor
.MemoryBaseAddress
;
2287 Status
= CoreGetMemorySpaceDescriptor (BaseAddress
, &Descriptor
);
2288 if (!EFI_ERROR (Status
)) {
2289 Status
= CoreAllocateMemorySpace (
2290 EfiGcdAllocateAddress
,
2291 Descriptor
.GcdMemoryType
,
2293 MemoryHob
->AllocDescriptor
.MemoryLength
,
2295 gDxeCoreImageHandle
,
2298 if (!EFI_ERROR (Status
) && Descriptor
.GcdMemoryType
== EfiGcdMemoryTypeSystemMemory
) {
2299 CoreAddMemoryDescriptor (
2300 MemoryHob
->AllocDescriptor
.MemoryType
,
2301 MemoryHob
->AllocDescriptor
.MemoryBaseAddress
,
2302 RShiftU64 (MemoryHob
->AllocDescriptor
.MemoryLength
, EFI_PAGE_SHIFT
),
2303 Descriptor
.Capabilities
& (~EFI_MEMORY_RUNTIME
)
2309 if (GET_HOB_TYPE (Hob
) == EFI_HOB_TYPE_FV
) {
2310 FirmwareVolumeHob
= Hob
.FirmwareVolume
;
2311 BaseAddress
= FirmwareVolumeHob
->BaseAddress
;
2312 Status
= CoreAllocateMemorySpace (
2313 EfiGcdAllocateAddress
,
2314 EfiGcdMemoryTypeMemoryMappedIo
,
2316 FirmwareVolumeHob
->Length
,
2318 gDxeCoreImageHandle
,
2325 // Relocate HOB List to an allocated pool buffer.
2327 NewHobList
= AllocateCopyPool (
2328 (UINTN
)PhitHob
->EfiFreeMemoryBottom
- (UINTN
)(*HobStart
),
2331 ASSERT (NewHobList
!= NULL
);
2333 *HobStart
= NewHobList
;
2334 gHobList
= NewHobList
;
2337 // Add and allocate the remaining unallocated system memory to the memory services.
2339 Status
= CoreGetMemorySpaceMap (&NumberOfDescriptors
, &MemorySpaceMap
);
2340 ASSERT (Status
== EFI_SUCCESS
);
2342 for (Index
= 0; Index
< NumberOfDescriptors
; Index
++) {
2343 if (MemorySpaceMap
[Index
].GcdMemoryType
== EfiGcdMemoryTypeSystemMemory
) {
2344 if (MemorySpaceMap
[Index
].ImageHandle
== NULL
) {
2345 BaseAddress
= PageAlignAddress (MemorySpaceMap
[Index
].BaseAddress
);
2346 Length
= PageAlignLength (MemorySpaceMap
[Index
].BaseAddress
+ MemorySpaceMap
[Index
].Length
- BaseAddress
);
2347 if (Length
== 0 || MemorySpaceMap
[Index
].BaseAddress
+ MemorySpaceMap
[Index
].Length
< BaseAddress
) {
2350 CoreAddMemoryDescriptor (
2351 EfiConventionalMemory
,
2353 RShiftU64 (Length
, EFI_PAGE_SHIFT
),
2354 MemorySpaceMap
[Index
].Capabilities
& (~EFI_MEMORY_RUNTIME
)
2356 Status
= CoreAllocateMemorySpace (
2357 EfiGcdAllocateAddress
,
2358 EfiGcdMemoryTypeSystemMemory
,
2362 gDxeCoreImageHandle
,
2368 CoreFreePool (MemorySpaceMap
);