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 - 2014, 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_PROTECTABLE
, EFI_MEMORY_RP
, TRUE
},
90 { EFI_RESOURCE_ATTRIBUTE_WRITE_PROTECTABLE
, EFI_MEMORY_WP
, TRUE
},
91 { EFI_RESOURCE_ATTRIBUTE_EXECUTION_PROTECTABLE
, 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 (Status
== EFI_SUCCESS
&& MemorySpaceMap
!= NULL
);
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 (Status
== EFI_SUCCESS
&& IoSpaceMap
!= NULL
);
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
);
215 Validate resource descriptor HOB's attributes.
217 If Attributes includes some memory resource's settings, it should include
218 the corresponding capabilites also.
220 @param Attributes Resource descriptor HOB attributes.
224 CoreValidateResourceDescriptorHobAttributes (
228 ASSERT (((Attributes
& EFI_RESOURCE_ATTRIBUTE_READ_PROTECTED
) == 0) ||
229 ((Attributes
& EFI_RESOURCE_ATTRIBUTE_READ_PROTECTABLE
) != 0));
230 ASSERT (((Attributes
& EFI_RESOURCE_ATTRIBUTE_WRITE_PROTECTED
) == 0) ||
231 ((Attributes
& EFI_RESOURCE_ATTRIBUTE_WRITE_PROTECTABLE
) != 0));
232 ASSERT (((Attributes
& EFI_RESOURCE_ATTRIBUTE_EXECUTION_PROTECTED
) == 0) ||
233 ((Attributes
& EFI_RESOURCE_ATTRIBUTE_EXECUTION_PROTECTABLE
) != 0));
237 Acquire memory lock on mGcdMemorySpaceLock.
241 CoreAcquireGcdMemoryLock (
245 CoreAcquireLock (&mGcdMemorySpaceLock
);
251 Release memory lock on mGcdMemorySpaceLock.
255 CoreReleaseGcdMemoryLock (
259 CoreReleaseLock (&mGcdMemorySpaceLock
);
265 Acquire memory lock on mGcdIoSpaceLock.
269 CoreAcquireGcdIoLock (
273 CoreAcquireLock (&mGcdIoSpaceLock
);
278 Release memory lock on mGcdIoSpaceLock.
282 CoreReleaseGcdIoLock (
286 CoreReleaseLock (&mGcdIoSpaceLock
);
292 // GCD Initialization Worker Functions
295 Aligns a value to the specified boundary.
297 @param Value 64 bit value to align
298 @param Alignment Log base 2 of the boundary to align Value to
299 @param RoundUp TRUE if Value is to be rounded up to the nearest
300 aligned boundary. FALSE is Value is to be
301 rounded down to the nearest aligned boundary.
303 @return A 64 bit value is the aligned to the value nearest Value with an alignment by Alignment.
313 UINT64 AlignmentMask
;
315 AlignmentMask
= LShiftU64 (1, Alignment
) - 1;
317 Value
+= AlignmentMask
;
319 return Value
& (~AlignmentMask
);
324 Aligns address to the page boundary.
326 @param Value 64 bit address to align
328 @return A 64 bit value is the aligned to the value nearest Value with an alignment by Alignment.
336 return AlignValue (Value
, EFI_PAGE_SHIFT
, TRUE
);
341 Aligns length to the page boundary.
343 @param Value 64 bit length to align
345 @return A 64 bit value is the aligned to the value nearest Value with an alignment by Alignment.
353 return AlignValue (Value
, EFI_PAGE_SHIFT
, FALSE
);
357 // GCD Memory Space Worker Functions
361 Allocate pool for two entries.
363 @param TopEntry An entry of GCD map
364 @param BottomEntry An entry of GCD map
366 @retval EFI_OUT_OF_RESOURCES No enough buffer to be allocated.
367 @retval EFI_SUCCESS Both entries successfully allocated.
371 CoreAllocateGcdMapEntry (
372 IN OUT EFI_GCD_MAP_ENTRY
**TopEntry
,
373 IN OUT EFI_GCD_MAP_ENTRY
**BottomEntry
376 *TopEntry
= AllocateZeroPool (sizeof (EFI_GCD_MAP_ENTRY
));
377 if (*TopEntry
== NULL
) {
378 return EFI_OUT_OF_RESOURCES
;
381 *BottomEntry
= AllocateZeroPool (sizeof (EFI_GCD_MAP_ENTRY
));
382 if (*BottomEntry
== NULL
) {
383 CoreFreePool (*TopEntry
);
384 return EFI_OUT_OF_RESOURCES
;
392 Internal function. Inserts a new descriptor into a sorted list
394 @param Link The linked list to insert the range BaseAddress
396 @param Entry A pointer to the entry that is inserted
397 @param BaseAddress The base address of the new range
398 @param Length The length of the new range in bytes
399 @param TopEntry Top pad entry to insert if needed.
400 @param BottomEntry Bottom pad entry to insert if needed.
402 @retval EFI_SUCCESS The new range was inserted into the linked list
406 CoreInsertGcdMapEntry (
408 IN EFI_GCD_MAP_ENTRY
*Entry
,
409 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
411 IN EFI_GCD_MAP_ENTRY
*TopEntry
,
412 IN EFI_GCD_MAP_ENTRY
*BottomEntry
415 ASSERT (Length
!= 0);
417 if (BaseAddress
> Entry
->BaseAddress
) {
418 ASSERT (BottomEntry
->Signature
== 0);
420 CopyMem (BottomEntry
, Entry
, sizeof (EFI_GCD_MAP_ENTRY
));
421 Entry
->BaseAddress
= BaseAddress
;
422 BottomEntry
->EndAddress
= BaseAddress
- 1;
423 InsertTailList (Link
, &BottomEntry
->Link
);
426 if ((BaseAddress
+ Length
- 1) < Entry
->EndAddress
) {
427 ASSERT (TopEntry
->Signature
== 0);
429 CopyMem (TopEntry
, Entry
, sizeof (EFI_GCD_MAP_ENTRY
));
430 TopEntry
->BaseAddress
= BaseAddress
+ Length
;
431 Entry
->EndAddress
= BaseAddress
+ Length
- 1;
432 InsertHeadList (Link
, &TopEntry
->Link
);
440 Merge the Gcd region specified by Link and its adjacent entry.
442 @param Link Specify the entry to be merged (with its
444 @param Forward Direction (forward or backward).
447 @retval EFI_SUCCESS Successfully returned.
448 @retval EFI_UNSUPPORTED These adjacent regions could not merge.
452 CoreMergeGcdMapEntry (
458 LIST_ENTRY
*AdjacentLink
;
459 EFI_GCD_MAP_ENTRY
*Entry
;
460 EFI_GCD_MAP_ENTRY
*AdjacentEntry
;
463 // Get adjacent entry
466 AdjacentLink
= Link
->ForwardLink
;
468 AdjacentLink
= Link
->BackLink
;
472 // If AdjacentLink is the head of the list, then no merge can be performed
474 if (AdjacentLink
== Map
) {
478 Entry
= CR (Link
, EFI_GCD_MAP_ENTRY
, Link
, EFI_GCD_MAP_SIGNATURE
);
479 AdjacentEntry
= CR (AdjacentLink
, EFI_GCD_MAP_ENTRY
, Link
, EFI_GCD_MAP_SIGNATURE
);
481 if (Entry
->Capabilities
!= AdjacentEntry
->Capabilities
) {
482 return EFI_UNSUPPORTED
;
484 if (Entry
->Attributes
!= AdjacentEntry
->Attributes
) {
485 return EFI_UNSUPPORTED
;
487 if (Entry
->GcdMemoryType
!= AdjacentEntry
->GcdMemoryType
) {
488 return EFI_UNSUPPORTED
;
490 if (Entry
->GcdIoType
!= AdjacentEntry
->GcdIoType
) {
491 return EFI_UNSUPPORTED
;
493 if (Entry
->ImageHandle
!= AdjacentEntry
->ImageHandle
) {
494 return EFI_UNSUPPORTED
;
496 if (Entry
->DeviceHandle
!= AdjacentEntry
->DeviceHandle
) {
497 return EFI_UNSUPPORTED
;
501 Entry
->EndAddress
= AdjacentEntry
->EndAddress
;
503 Entry
->BaseAddress
= AdjacentEntry
->BaseAddress
;
505 RemoveEntryList (AdjacentLink
);
506 CoreFreePool (AdjacentEntry
);
513 Merge adjacent entries on total chain.
515 @param TopEntry Top entry of GCD map.
516 @param BottomEntry Bottom entry of GCD map.
517 @param StartLink Start link of the list for this loop.
518 @param EndLink End link of the list for this loop.
521 @retval EFI_SUCCESS GCD map successfully cleaned up.
525 CoreCleanupGcdMapEntry (
526 IN EFI_GCD_MAP_ENTRY
*TopEntry
,
527 IN EFI_GCD_MAP_ENTRY
*BottomEntry
,
528 IN LIST_ENTRY
*StartLink
,
529 IN LIST_ENTRY
*EndLink
,
535 if (TopEntry
->Signature
== 0) {
536 CoreFreePool (TopEntry
);
538 if (BottomEntry
->Signature
== 0) {
539 CoreFreePool (BottomEntry
);
543 while (Link
!= EndLink
->ForwardLink
) {
544 CoreMergeGcdMapEntry (Link
, FALSE
, Map
);
545 Link
= Link
->ForwardLink
;
547 CoreMergeGcdMapEntry (EndLink
, TRUE
, Map
);
554 Search a segment of memory space in GCD map. The result is a range of GCD entry list.
556 @param BaseAddress The start address of the segment.
557 @param Length The length of the segment.
558 @param StartLink The first GCD entry involves this segment of
560 @param EndLink The first GCD entry involves this segment of
562 @param Map Points to the start entry to search.
564 @retval EFI_SUCCESS Successfully found the entry.
565 @retval EFI_NOT_FOUND Not found.
569 CoreSearchGcdMapEntry (
570 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
572 OUT LIST_ENTRY
**StartLink
,
573 OUT LIST_ENTRY
**EndLink
,
578 EFI_GCD_MAP_ENTRY
*Entry
;
580 ASSERT (Length
!= 0);
585 Link
= Map
->ForwardLink
;
586 while (Link
!= Map
) {
587 Entry
= CR (Link
, EFI_GCD_MAP_ENTRY
, Link
, EFI_GCD_MAP_SIGNATURE
);
588 if (BaseAddress
>= Entry
->BaseAddress
&& BaseAddress
<= Entry
->EndAddress
) {
591 if (*StartLink
!= NULL
) {
592 if ((BaseAddress
+ Length
- 1) >= Entry
->BaseAddress
&&
593 (BaseAddress
+ Length
- 1) <= Entry
->EndAddress
) {
598 Link
= Link
->ForwardLink
;
601 return EFI_NOT_FOUND
;
606 Count the amount of GCD map entries.
608 @param Map Points to the start entry to do the count loop.
614 CoreCountGcdMapEntry (
622 Link
= Map
->ForwardLink
;
623 while (Link
!= Map
) {
625 Link
= Link
->ForwardLink
;
634 Return the memory attribute specified by Attributes
636 @param Attributes A num with some attribute bits on.
638 @return The enum value of memory attribute.
642 ConverToCpuArchAttributes (
646 if ( (Attributes
& EFI_MEMORY_UC
) == EFI_MEMORY_UC
) {
647 return EFI_MEMORY_UC
;
650 if ( (Attributes
& EFI_MEMORY_WC
) == EFI_MEMORY_WC
) {
651 return EFI_MEMORY_WC
;
654 if ( (Attributes
& EFI_MEMORY_WT
) == EFI_MEMORY_WT
) {
655 return EFI_MEMORY_WT
;
658 if ( (Attributes
& EFI_MEMORY_WB
) == EFI_MEMORY_WB
) {
659 return EFI_MEMORY_WB
;
662 if ( (Attributes
& EFI_MEMORY_WP
) == EFI_MEMORY_WP
) {
663 return EFI_MEMORY_WP
;
666 return INVALID_CPU_ARCH_ATTRIBUTES
;
672 Do operation on a segment of memory space specified (add, free, remove, change attribute ...).
674 @param Operation The type of the operation
675 @param GcdMemoryType Additional information for the operation
676 @param GcdIoType Additional information for the operation
677 @param BaseAddress Start address of the segment
678 @param Length length of the segment
679 @param Capabilities The alterable attributes of a newly added entry
680 @param Attributes The attributes needs to be set
682 @retval EFI_INVALID_PARAMETER Length is 0 or address (length) not aligned when
684 @retval EFI_SUCCESS Action successfully done.
685 @retval EFI_UNSUPPORTED Could not find the proper descriptor on this
686 segment or set an upsupported attribute.
687 @retval EFI_ACCESS_DENIED Operate on an space non-exist or is used for an
689 @retval EFI_NOT_FOUND Free a non-using space or remove a non-exist
691 @retval EFI_OUT_OF_RESOURCES No buffer could be allocated.
692 @retval EFI_NOT_AVAILABLE_YET The attributes cannot be set because CPU architectural protocol
693 is not available yet.
698 IN EFI_GCD_MEMORY_TYPE GcdMemoryType
,
699 IN EFI_GCD_IO_TYPE GcdIoType
,
700 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
702 IN UINT64 Capabilities
,
709 EFI_GCD_MAP_ENTRY
*Entry
;
710 EFI_GCD_MAP_ENTRY
*TopEntry
;
711 EFI_GCD_MAP_ENTRY
*BottomEntry
;
712 LIST_ENTRY
*StartLink
;
714 UINT64 CpuArchAttributes
;
717 DEBUG ((DEBUG_GCD
, " Status = %r\n", EFI_INVALID_PARAMETER
));
718 return EFI_INVALID_PARAMETER
;
722 if ((Operation
& GCD_MEMORY_SPACE_OPERATION
) != 0) {
723 CoreAcquireGcdMemoryLock ();
724 Map
= &mGcdMemorySpaceMap
;
725 } else if ((Operation
& GCD_IO_SPACE_OPERATION
) != 0) {
726 CoreAcquireGcdIoLock ();
727 Map
= &mGcdIoSpaceMap
;
733 // Search for the list of descriptors that cover the range BaseAddress to BaseAddress+Length
735 Status
= CoreSearchGcdMapEntry (BaseAddress
, Length
, &StartLink
, &EndLink
, Map
);
736 if (EFI_ERROR (Status
)) {
737 Status
= EFI_UNSUPPORTED
;
741 ASSERT (StartLink
!= NULL
&& EndLink
!= NULL
);
744 // Verify that the list of descriptors are unallocated non-existent memory.
747 while (Link
!= EndLink
->ForwardLink
) {
748 Entry
= CR (Link
, EFI_GCD_MAP_ENTRY
, Link
, EFI_GCD_MAP_SIGNATURE
);
753 case GCD_ADD_MEMORY_OPERATION
:
754 if (Entry
->GcdMemoryType
!= EfiGcdMemoryTypeNonExistent
||
755 Entry
->ImageHandle
!= NULL
) {
756 Status
= EFI_ACCESS_DENIED
;
760 case GCD_ADD_IO_OPERATION
:
761 if (Entry
->GcdIoType
!= EfiGcdIoTypeNonExistent
||
762 Entry
->ImageHandle
!= NULL
) {
763 Status
= EFI_ACCESS_DENIED
;
770 case GCD_FREE_MEMORY_OPERATION
:
771 case GCD_FREE_IO_OPERATION
:
772 if (Entry
->ImageHandle
== NULL
) {
773 Status
= EFI_NOT_FOUND
;
780 case GCD_REMOVE_MEMORY_OPERATION
:
781 if (Entry
->GcdMemoryType
== EfiGcdMemoryTypeNonExistent
) {
782 Status
= EFI_NOT_FOUND
;
785 if (Entry
->ImageHandle
!= NULL
) {
786 Status
= EFI_ACCESS_DENIED
;
790 case GCD_REMOVE_IO_OPERATION
:
791 if (Entry
->GcdIoType
== EfiGcdIoTypeNonExistent
) {
792 Status
= EFI_NOT_FOUND
;
795 if (Entry
->ImageHandle
!= NULL
) {
796 Status
= EFI_ACCESS_DENIED
;
801 // Set attributes operation
803 case GCD_SET_ATTRIBUTES_MEMORY_OPERATION
:
804 if ((Attributes
& EFI_MEMORY_RUNTIME
) != 0) {
805 if ((BaseAddress
& EFI_PAGE_MASK
) != 0 || (Length
& EFI_PAGE_MASK
) != 0) {
806 Status
= EFI_INVALID_PARAMETER
;
810 if ((Entry
->Capabilities
& Attributes
) != Attributes
) {
811 Status
= EFI_UNSUPPORTED
;
816 // Set capabilities operation
818 case GCD_SET_CAPABILITIES_MEMORY_OPERATION
:
819 if ((BaseAddress
& EFI_PAGE_MASK
) != 0 || (Length
& EFI_PAGE_MASK
) != 0) {
820 Status
= EFI_INVALID_PARAMETER
;
825 // Current attributes must still be supported with new capabilities
827 if ((Capabilities
& Entry
->Attributes
) != Entry
->Attributes
) {
828 Status
= EFI_UNSUPPORTED
;
833 Link
= Link
->ForwardLink
;
837 // Allocate work space to perform this operation
839 Status
= CoreAllocateGcdMapEntry (&TopEntry
, &BottomEntry
);
840 if (EFI_ERROR (Status
)) {
841 Status
= EFI_OUT_OF_RESOURCES
;
844 ASSERT (TopEntry
!= NULL
&& BottomEntry
!= NULL
);
846 if (Operation
== GCD_SET_ATTRIBUTES_MEMORY_OPERATION
) {
848 // Call CPU Arch Protocol to attempt to set attributes on the range
850 CpuArchAttributes
= ConverToCpuArchAttributes (Attributes
);
851 if (CpuArchAttributes
!= INVALID_CPU_ARCH_ATTRIBUTES
) {
853 Status
= EFI_NOT_AVAILABLE_YET
;
855 Status
= gCpu
->SetMemoryAttributes (
862 if (EFI_ERROR (Status
)) {
863 CoreFreePool (TopEntry
);
864 CoreFreePool (BottomEntry
);
871 // Convert/Insert the list of descriptors from StartLink to EndLink
874 while (Link
!= EndLink
->ForwardLink
) {
875 Entry
= CR (Link
, EFI_GCD_MAP_ENTRY
, Link
, EFI_GCD_MAP_SIGNATURE
);
876 CoreInsertGcdMapEntry (Link
, Entry
, BaseAddress
, Length
, TopEntry
, BottomEntry
);
881 case GCD_ADD_MEMORY_OPERATION
:
882 Entry
->GcdMemoryType
= GcdMemoryType
;
883 if (GcdMemoryType
== EfiGcdMemoryTypeMemoryMappedIo
) {
884 Entry
->Capabilities
= Capabilities
| EFI_MEMORY_RUNTIME
| EFI_MEMORY_PORT_IO
;
886 Entry
->Capabilities
= Capabilities
| EFI_MEMORY_RUNTIME
;
889 case GCD_ADD_IO_OPERATION
:
890 Entry
->GcdIoType
= GcdIoType
;
895 case GCD_FREE_MEMORY_OPERATION
:
896 case GCD_FREE_IO_OPERATION
:
897 Entry
->ImageHandle
= NULL
;
898 Entry
->DeviceHandle
= NULL
;
903 case GCD_REMOVE_MEMORY_OPERATION
:
904 Entry
->GcdMemoryType
= EfiGcdMemoryTypeNonExistent
;
905 Entry
->Capabilities
= 0;
907 case GCD_REMOVE_IO_OPERATION
:
908 Entry
->GcdIoType
= EfiGcdIoTypeNonExistent
;
911 // Set attributes operation
913 case GCD_SET_ATTRIBUTES_MEMORY_OPERATION
:
914 Entry
->Attributes
= Attributes
;
917 // Set capabilities operation
919 case GCD_SET_CAPABILITIES_MEMORY_OPERATION
:
920 Entry
->Capabilities
= Capabilities
;
923 Link
= Link
->ForwardLink
;
929 Status
= CoreCleanupGcdMapEntry (TopEntry
, BottomEntry
, StartLink
, EndLink
, Map
);
932 DEBUG ((DEBUG_GCD
, " Status = %r\n", Status
));
934 if ((Operation
& GCD_MEMORY_SPACE_OPERATION
) != 0) {
935 CoreReleaseGcdMemoryLock ();
936 CoreDumpGcdMemorySpaceMap (FALSE
);
938 if ((Operation
& GCD_IO_SPACE_OPERATION
) != 0) {
939 CoreReleaseGcdIoLock ();
940 CoreDumpGcdIoSpaceMap (FALSE
);
948 Check whether an entry could be used to allocate space.
950 @param Operation Allocate memory or IO
951 @param Entry The entry to be tested
952 @param GcdMemoryType The desired memory type
953 @param GcdIoType The desired IO type
955 @retval EFI_NOT_FOUND The memory type does not match or there's an
956 image handle on the entry.
957 @retval EFI_UNSUPPORTED The operation unsupported.
958 @retval EFI_SUCCESS It's ok for this entry to be used to allocate
963 CoreAllocateSpaceCheckEntry (
965 IN EFI_GCD_MAP_ENTRY
*Entry
,
966 IN EFI_GCD_MEMORY_TYPE GcdMemoryType
,
967 IN EFI_GCD_IO_TYPE GcdIoType
970 if (Entry
->ImageHandle
!= NULL
) {
971 return EFI_NOT_FOUND
;
974 case GCD_ALLOCATE_MEMORY_OPERATION
:
975 if (Entry
->GcdMemoryType
!= GcdMemoryType
) {
976 return EFI_NOT_FOUND
;
979 case GCD_ALLOCATE_IO_OPERATION
:
980 if (Entry
->GcdIoType
!= GcdIoType
) {
981 return EFI_NOT_FOUND
;
985 return EFI_UNSUPPORTED
;
992 Allocate space on specified address and length.
994 @param Operation The type of operation (memory or IO)
995 @param GcdAllocateType The type of allocate operation
996 @param GcdMemoryType The desired memory type
997 @param GcdIoType The desired IO type
998 @param Alignment Align with 2^Alignment
999 @param Length Length to allocate
1000 @param BaseAddress Base address to allocate
1001 @param ImageHandle The image handle consume the allocated space.
1002 @param DeviceHandle The device handle consume the allocated space.
1004 @retval EFI_INVALID_PARAMETER Invalid parameter.
1005 @retval EFI_NOT_FOUND No descriptor for the desired space exists.
1006 @retval EFI_SUCCESS Space successfully allocated.
1012 IN EFI_GCD_ALLOCATE_TYPE GcdAllocateType
,
1013 IN EFI_GCD_MEMORY_TYPE GcdMemoryType
,
1014 IN EFI_GCD_IO_TYPE GcdIoType
,
1017 IN OUT EFI_PHYSICAL_ADDRESS
*BaseAddress
,
1018 IN EFI_HANDLE ImageHandle
,
1019 IN EFI_HANDLE DeviceHandle OPTIONAL
1023 EFI_PHYSICAL_ADDRESS AlignmentMask
;
1024 EFI_PHYSICAL_ADDRESS MaxAddress
;
1027 LIST_ENTRY
*SubLink
;
1028 EFI_GCD_MAP_ENTRY
*Entry
;
1029 EFI_GCD_MAP_ENTRY
*TopEntry
;
1030 EFI_GCD_MAP_ENTRY
*BottomEntry
;
1031 LIST_ENTRY
*StartLink
;
1032 LIST_ENTRY
*EndLink
;
1036 // Make sure parameters are valid
1038 if ((UINT32
)GcdAllocateType
>= EfiGcdMaxAllocateType
) {
1039 DEBUG ((DEBUG_GCD
, " Status = %r\n", EFI_INVALID_PARAMETER
));
1040 return EFI_INVALID_PARAMETER
;
1042 if ((UINT32
)GcdMemoryType
>= EfiGcdMemoryTypeMaximum
) {
1043 DEBUG ((DEBUG_GCD
, " Status = %r\n", EFI_INVALID_PARAMETER
));
1044 return EFI_INVALID_PARAMETER
;
1046 if ((UINT32
)GcdIoType
>= EfiGcdIoTypeMaximum
) {
1047 DEBUG ((DEBUG_GCD
, " Status = %r\n", EFI_INVALID_PARAMETER
));
1048 return EFI_INVALID_PARAMETER
;
1050 if (BaseAddress
== NULL
) {
1051 DEBUG ((DEBUG_GCD
, " Status = %r\n", EFI_INVALID_PARAMETER
));
1052 return EFI_INVALID_PARAMETER
;
1054 if (ImageHandle
== NULL
) {
1055 DEBUG ((DEBUG_GCD
, " Status = %r\n", EFI_INVALID_PARAMETER
));
1056 return EFI_INVALID_PARAMETER
;
1058 if (Alignment
>= 64) {
1059 DEBUG ((DEBUG_GCD
, " Status = %r\n", EFI_NOT_FOUND
));
1060 return EFI_NOT_FOUND
;
1063 DEBUG ((DEBUG_GCD
, " Status = %r\n", EFI_INVALID_PARAMETER
));
1064 return EFI_INVALID_PARAMETER
;
1068 if ((Operation
& GCD_MEMORY_SPACE_OPERATION
) != 0) {
1069 CoreAcquireGcdMemoryLock ();
1070 Map
= &mGcdMemorySpaceMap
;
1071 } else if ((Operation
& GCD_IO_SPACE_OPERATION
) != 0) {
1072 CoreAcquireGcdIoLock ();
1073 Map
= &mGcdIoSpaceMap
;
1082 // Compute alignment bit mask
1084 AlignmentMask
= LShiftU64 (1, Alignment
) - 1;
1086 if (GcdAllocateType
== EfiGcdAllocateAddress
) {
1088 // Verify that the BaseAddress passed in is aligned correctly
1090 if ((*BaseAddress
& AlignmentMask
) != 0) {
1091 Status
= EFI_NOT_FOUND
;
1096 // Search for the list of descriptors that cover the range BaseAddress to BaseAddress+Length
1098 Status
= CoreSearchGcdMapEntry (*BaseAddress
, Length
, &StartLink
, &EndLink
, Map
);
1099 if (EFI_ERROR (Status
)) {
1100 Status
= EFI_NOT_FOUND
;
1103 ASSERT (StartLink
!= NULL
&& EndLink
!= NULL
);
1106 // Verify that the list of descriptors are unallocated memory matching GcdMemoryType.
1109 while (Link
!= EndLink
->ForwardLink
) {
1110 Entry
= CR (Link
, EFI_GCD_MAP_ENTRY
, Link
, EFI_GCD_MAP_SIGNATURE
);
1111 Link
= Link
->ForwardLink
;
1112 Status
= CoreAllocateSpaceCheckEntry (Operation
, Entry
, GcdMemoryType
, GcdIoType
);
1113 if (EFI_ERROR (Status
)) {
1120 Entry
= CR (Map
->BackLink
, EFI_GCD_MAP_ENTRY
, Link
, EFI_GCD_MAP_SIGNATURE
);
1123 // Compute the maximum address to use in the search algorithm
1125 if (GcdAllocateType
== EfiGcdAllocateMaxAddressSearchBottomUp
||
1126 GcdAllocateType
== EfiGcdAllocateMaxAddressSearchTopDown
) {
1127 MaxAddress
= *BaseAddress
;
1129 MaxAddress
= Entry
->EndAddress
;
1133 // Verify that the list of descriptors are unallocated memory matching GcdMemoryType.
1135 if (GcdAllocateType
== EfiGcdAllocateMaxAddressSearchTopDown
||
1136 GcdAllocateType
== EfiGcdAllocateAnySearchTopDown
) {
1137 Link
= Map
->BackLink
;
1139 Link
= Map
->ForwardLink
;
1141 while (Link
!= Map
) {
1142 Entry
= CR (Link
, EFI_GCD_MAP_ENTRY
, Link
, EFI_GCD_MAP_SIGNATURE
);
1144 if (GcdAllocateType
== EfiGcdAllocateMaxAddressSearchTopDown
||
1145 GcdAllocateType
== EfiGcdAllocateAnySearchTopDown
) {
1146 Link
= Link
->BackLink
;
1148 Link
= Link
->ForwardLink
;
1151 Status
= CoreAllocateSpaceCheckEntry (Operation
, Entry
, GcdMemoryType
, GcdIoType
);
1152 if (EFI_ERROR (Status
)) {
1156 if (GcdAllocateType
== EfiGcdAllocateMaxAddressSearchTopDown
||
1157 GcdAllocateType
== EfiGcdAllocateAnySearchTopDown
) {
1158 if ((Entry
->BaseAddress
+ Length
) > MaxAddress
) {
1161 if (Length
> (Entry
->EndAddress
+ 1)) {
1162 Status
= EFI_NOT_FOUND
;
1165 if (Entry
->EndAddress
> MaxAddress
) {
1166 *BaseAddress
= MaxAddress
;
1168 *BaseAddress
= Entry
->EndAddress
;
1170 *BaseAddress
= (*BaseAddress
+ 1 - Length
) & (~AlignmentMask
);
1172 *BaseAddress
= (Entry
->BaseAddress
+ AlignmentMask
) & (~AlignmentMask
);
1173 if ((*BaseAddress
+ Length
- 1) > MaxAddress
) {
1174 Status
= EFI_NOT_FOUND
;
1180 // Search for the list of descriptors that cover the range BaseAddress to BaseAddress+Length
1182 Status
= CoreSearchGcdMapEntry (*BaseAddress
, Length
, &StartLink
, &EndLink
, Map
);
1183 if (EFI_ERROR (Status
)) {
1184 Status
= EFI_NOT_FOUND
;
1187 ASSERT (StartLink
!= NULL
&& EndLink
!= NULL
);
1191 // Verify that the list of descriptors are unallocated memory matching GcdMemoryType.
1194 SubLink
= StartLink
;
1195 while (SubLink
!= EndLink
->ForwardLink
) {
1196 Entry
= CR (SubLink
, EFI_GCD_MAP_ENTRY
, Link
, EFI_GCD_MAP_SIGNATURE
);
1197 Status
= CoreAllocateSpaceCheckEntry (Operation
, Entry
, GcdMemoryType
, GcdIoType
);
1198 if (EFI_ERROR (Status
)) {
1203 SubLink
= SubLink
->ForwardLink
;
1211 Status
= EFI_NOT_FOUND
;
1216 // Allocate work space to perform this operation
1218 Status
= CoreAllocateGcdMapEntry (&TopEntry
, &BottomEntry
);
1219 if (EFI_ERROR (Status
)) {
1220 Status
= EFI_OUT_OF_RESOURCES
;
1223 ASSERT (TopEntry
!= NULL
&& BottomEntry
!= NULL
);
1226 // Convert/Insert the list of descriptors from StartLink to EndLink
1229 while (Link
!= EndLink
->ForwardLink
) {
1230 Entry
= CR (Link
, EFI_GCD_MAP_ENTRY
, Link
, EFI_GCD_MAP_SIGNATURE
);
1231 CoreInsertGcdMapEntry (Link
, Entry
, *BaseAddress
, Length
, TopEntry
, BottomEntry
);
1232 Entry
->ImageHandle
= ImageHandle
;
1233 Entry
->DeviceHandle
= DeviceHandle
;
1234 Link
= Link
->ForwardLink
;
1240 Status
= CoreCleanupGcdMapEntry (TopEntry
, BottomEntry
, StartLink
, EndLink
, Map
);
1243 DEBUG ((DEBUG_GCD
, " Status = %r", Status
));
1244 if (!EFI_ERROR (Status
)) {
1245 DEBUG ((DEBUG_GCD
, " (BaseAddress = %016lx)", *BaseAddress
));
1247 DEBUG ((DEBUG_GCD
, "\n"));
1249 if ((Operation
& GCD_MEMORY_SPACE_OPERATION
) != 0) {
1250 CoreReleaseGcdMemoryLock ();
1251 CoreDumpGcdMemorySpaceMap (FALSE
);
1253 if ((Operation
& GCD_IO_SPACE_OPERATION
) !=0) {
1254 CoreReleaseGcdIoLock ();
1255 CoreDumpGcdIoSpaceMap (FALSE
);
1263 Add a segment of memory to GCD map.
1265 @param GcdMemoryType Memory type of the segment.
1266 @param BaseAddress Base address of the segment.
1267 @param Length Length of the segment.
1268 @param Capabilities alterable attributes of the segment.
1270 @retval EFI_INVALID_PARAMETER Invalid parameters.
1271 @retval EFI_SUCCESS Successfully add a segment of memory space.
1275 CoreInternalAddMemorySpace (
1276 IN EFI_GCD_MEMORY_TYPE GcdMemoryType
,
1277 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
1279 IN UINT64 Capabilities
1282 DEBUG ((DEBUG_GCD
, "GCD:AddMemorySpace(Base=%016lx,Length=%016lx)\n", BaseAddress
, Length
));
1283 DEBUG ((DEBUG_GCD
, " GcdMemoryType = %a\n", mGcdMemoryTypeNames
[MIN (GcdMemoryType
, EfiGcdMemoryTypeMaximum
)]));
1284 DEBUG ((DEBUG_GCD
, " Capabilities = %016lx\n", Capabilities
));
1287 // Make sure parameters are valid
1289 if (GcdMemoryType
<= EfiGcdMemoryTypeNonExistent
|| GcdMemoryType
>= EfiGcdMemoryTypeMaximum
) {
1290 return EFI_INVALID_PARAMETER
;
1293 return CoreConvertSpace (GCD_ADD_MEMORY_OPERATION
, GcdMemoryType
, (EFI_GCD_IO_TYPE
) 0, BaseAddress
, Length
, Capabilities
, 0);
1297 // GCD Core Services
1301 Allocates nonexistent memory, reserved memory, system memory, or memorymapped
1302 I/O resources from the global coherency domain of the processor.
1304 @param GcdAllocateType The type of allocate operation
1305 @param GcdMemoryType The desired memory type
1306 @param Alignment Align with 2^Alignment
1307 @param Length Length to allocate
1308 @param BaseAddress Base address to allocate
1309 @param ImageHandle The image handle consume the allocated space.
1310 @param DeviceHandle The device handle consume the allocated space.
1312 @retval EFI_INVALID_PARAMETER Invalid parameter.
1313 @retval EFI_NOT_FOUND No descriptor contains the desired space.
1314 @retval EFI_SUCCESS Memory space successfully allocated.
1319 CoreAllocateMemorySpace (
1320 IN EFI_GCD_ALLOCATE_TYPE GcdAllocateType
,
1321 IN EFI_GCD_MEMORY_TYPE GcdMemoryType
,
1324 IN OUT EFI_PHYSICAL_ADDRESS
*BaseAddress
,
1325 IN EFI_HANDLE ImageHandle
,
1326 IN EFI_HANDLE DeviceHandle OPTIONAL
1329 DEBUG ((DEBUG_GCD
, "GCD:AllocateMemorySpace(Base=%016lx,Length=%016lx)\n", *BaseAddress
, Length
));
1330 DEBUG ((DEBUG_GCD
, " GcdAllocateType = %a\n", mGcdAllocationTypeNames
[MIN (GcdAllocateType
, EfiGcdMaxAllocateType
)]));
1331 DEBUG ((DEBUG_GCD
, " GcdMemoryType = %a\n", mGcdMemoryTypeNames
[MIN (GcdMemoryType
, EfiGcdMemoryTypeMaximum
)]));
1332 DEBUG ((DEBUG_GCD
, " Alignment = %016lx\n", LShiftU64 (1, Alignment
)));
1333 DEBUG ((DEBUG_GCD
, " ImageHandle = %p\n", ImageHandle
));
1334 DEBUG ((DEBUG_GCD
, " DeviceHandle = %p\n", DeviceHandle
));
1336 return CoreAllocateSpace (
1337 GCD_ALLOCATE_MEMORY_OPERATION
,
1340 (EFI_GCD_IO_TYPE
) 0,
1351 Adds reserved memory, system memory, or memory-mapped I/O resources to the
1352 global coherency domain of the processor.
1354 @param GcdMemoryType Memory type of the memory space.
1355 @param BaseAddress Base address of the memory space.
1356 @param Length Length of the memory space.
1357 @param Capabilities alterable attributes of the memory space.
1359 @retval EFI_SUCCESS Merged this memory space into GCD map.
1364 CoreAddMemorySpace (
1365 IN EFI_GCD_MEMORY_TYPE GcdMemoryType
,
1366 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
1368 IN UINT64 Capabilities
1372 EFI_PHYSICAL_ADDRESS PageBaseAddress
;
1375 Status
= CoreInternalAddMemorySpace (GcdMemoryType
, BaseAddress
, Length
, Capabilities
);
1377 if (!EFI_ERROR (Status
) && GcdMemoryType
== EfiGcdMemoryTypeSystemMemory
) {
1379 PageBaseAddress
= PageAlignLength (BaseAddress
);
1380 PageLength
= PageAlignLength (BaseAddress
+ Length
- PageBaseAddress
);
1382 Status
= CoreAllocateMemorySpace (
1383 EfiGcdAllocateAddress
,
1388 gDxeCoreImageHandle
,
1392 if (!EFI_ERROR (Status
)) {
1393 CoreAddMemoryDescriptor (
1394 EfiConventionalMemory
,
1396 RShiftU64 (PageLength
, EFI_PAGE_SHIFT
),
1400 for (; PageLength
!= 0; PageLength
-= EFI_PAGE_SIZE
, PageBaseAddress
+= EFI_PAGE_SIZE
) {
1401 Status
= CoreAllocateMemorySpace (
1402 EfiGcdAllocateAddress
,
1407 gDxeCoreImageHandle
,
1411 if (!EFI_ERROR (Status
)) {
1412 CoreAddMemoryDescriptor (
1413 EfiConventionalMemory
,
1427 Frees nonexistent memory, reserved memory, system memory, or memory-mapped
1428 I/O resources from the global coherency domain of the processor.
1430 @param BaseAddress Base address of the memory space.
1431 @param Length Length of the memory space.
1433 @retval EFI_SUCCESS Space successfully freed.
1438 CoreFreeMemorySpace (
1439 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
1443 DEBUG ((DEBUG_GCD
, "GCD:FreeMemorySpace(Base=%016lx,Length=%016lx)\n", BaseAddress
, Length
));
1445 return CoreConvertSpace (GCD_FREE_MEMORY_OPERATION
, (EFI_GCD_MEMORY_TYPE
) 0, (EFI_GCD_IO_TYPE
) 0, BaseAddress
, Length
, 0, 0);
1450 Removes reserved memory, system memory, or memory-mapped I/O resources from
1451 the global coherency domain of the processor.
1453 @param BaseAddress Base address of the memory space.
1454 @param Length Length of the memory space.
1456 @retval EFI_SUCCESS Successfully remove a segment of memory space.
1461 CoreRemoveMemorySpace (
1462 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
1466 DEBUG ((DEBUG_GCD
, "GCD:RemoveMemorySpace(Base=%016lx,Length=%016lx)\n", BaseAddress
, Length
));
1468 return CoreConvertSpace (GCD_REMOVE_MEMORY_OPERATION
, (EFI_GCD_MEMORY_TYPE
) 0, (EFI_GCD_IO_TYPE
) 0, BaseAddress
, Length
, 0, 0);
1473 Build a memory descriptor according to an entry.
1475 @param Descriptor The descriptor to be built
1476 @param Entry According to this entry
1480 BuildMemoryDescriptor (
1481 IN OUT EFI_GCD_MEMORY_SPACE_DESCRIPTOR
*Descriptor
,
1482 IN EFI_GCD_MAP_ENTRY
*Entry
1485 Descriptor
->BaseAddress
= Entry
->BaseAddress
;
1486 Descriptor
->Length
= Entry
->EndAddress
- Entry
->BaseAddress
+ 1;
1487 Descriptor
->Capabilities
= Entry
->Capabilities
;
1488 Descriptor
->Attributes
= Entry
->Attributes
;
1489 Descriptor
->GcdMemoryType
= Entry
->GcdMemoryType
;
1490 Descriptor
->ImageHandle
= Entry
->ImageHandle
;
1491 Descriptor
->DeviceHandle
= Entry
->DeviceHandle
;
1496 Retrieves the descriptor for a memory region containing a specified address.
1498 @param BaseAddress Specified start address
1499 @param Descriptor Specified length
1501 @retval EFI_INVALID_PARAMETER Invalid parameter
1502 @retval EFI_SUCCESS Successfully get memory space descriptor.
1507 CoreGetMemorySpaceDescriptor (
1508 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
1509 OUT EFI_GCD_MEMORY_SPACE_DESCRIPTOR
*Descriptor
1513 LIST_ENTRY
*StartLink
;
1514 LIST_ENTRY
*EndLink
;
1515 EFI_GCD_MAP_ENTRY
*Entry
;
1518 // Make sure parameters are valid
1520 if (Descriptor
== NULL
) {
1521 return EFI_INVALID_PARAMETER
;
1524 CoreAcquireGcdMemoryLock ();
1527 // Search for the list of descriptors that contain BaseAddress
1529 Status
= CoreSearchGcdMapEntry (BaseAddress
, 1, &StartLink
, &EndLink
, &mGcdMemorySpaceMap
);
1530 if (EFI_ERROR (Status
)) {
1531 Status
= EFI_NOT_FOUND
;
1533 ASSERT (StartLink
!= NULL
&& EndLink
!= NULL
);
1535 // Copy the contents of the found descriptor into Descriptor
1537 Entry
= CR (StartLink
, EFI_GCD_MAP_ENTRY
, Link
, EFI_GCD_MAP_SIGNATURE
);
1538 BuildMemoryDescriptor (Descriptor
, Entry
);
1541 CoreReleaseGcdMemoryLock ();
1548 Modifies the attributes for a memory region in the global coherency domain of the
1551 @param BaseAddress Specified start address
1552 @param Length Specified length
1553 @param Attributes Specified attributes
1555 @retval EFI_SUCCESS The attributes were set for the memory region.
1556 @retval EFI_INVALID_PARAMETER Length is zero.
1557 @retval EFI_UNSUPPORTED The processor does not support one or more bytes of the memory
1558 resource range specified by BaseAddress and Length.
1559 @retval EFI_UNSUPPORTED The bit mask of attributes is not support for the memory resource
1560 range specified by BaseAddress and Length.
1561 @retval EFI_ACCESS_DEFINED The attributes for the memory resource range specified by
1562 BaseAddress and Length cannot be modified.
1563 @retval EFI_OUT_OF_RESOURCES There are not enough system resources to modify the attributes of
1564 the memory resource range.
1565 @retval EFI_NOT_AVAILABLE_YET The attributes cannot be set because CPU architectural protocol is
1571 CoreSetMemorySpaceAttributes (
1572 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
1574 IN UINT64 Attributes
1577 DEBUG ((DEBUG_GCD
, "GCD:SetMemorySpaceAttributes(Base=%016lx,Length=%016lx)\n", BaseAddress
, Length
));
1578 DEBUG ((DEBUG_GCD
, " Attributes = %016lx\n", Attributes
));
1580 return CoreConvertSpace (GCD_SET_ATTRIBUTES_MEMORY_OPERATION
, (EFI_GCD_MEMORY_TYPE
) 0, (EFI_GCD_IO_TYPE
) 0, BaseAddress
, Length
, 0, Attributes
);
1585 Modifies the capabilities for a memory region in the global coherency domain of the
1588 @param BaseAddress The physical address that is the start address of a memory region.
1589 @param Length The size in bytes of the memory region.
1590 @param Capabilities The bit mask of capabilities that the memory region supports.
1592 @retval EFI_SUCCESS The capabilities were set for the memory region.
1593 @retval EFI_INVALID_PARAMETER Length is zero.
1594 @retval EFI_UNSUPPORTED The capabilities specified by Capabilities do not include the
1595 memory region attributes currently in use.
1596 @retval EFI_ACCESS_DENIED The capabilities for the memory resource range specified by
1597 BaseAddress and Length cannot be modified.
1598 @retval EFI_OUT_OF_RESOURCES There are not enough system resources to modify the capabilities
1599 of the memory resource range.
1603 CoreSetMemorySpaceCapabilities (
1604 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
1606 IN UINT64 Capabilities
1611 DEBUG ((DEBUG_GCD
, "GCD:CoreSetMemorySpaceCapabilities(Base=%016lx,Length=%016lx)\n", BaseAddress
, Length
));
1612 DEBUG ((DEBUG_GCD
, " Capabilities = %016lx\n", Capabilities
));
1614 Status
= CoreConvertSpace (GCD_SET_CAPABILITIES_MEMORY_OPERATION
, (EFI_GCD_MEMORY_TYPE
) 0, (EFI_GCD_IO_TYPE
) 0, BaseAddress
, Length
, Capabilities
, 0);
1615 if (!EFI_ERROR(Status
)) {
1616 CoreUpdateMemoryAttributes(BaseAddress
, RShiftU64(Length
, EFI_PAGE_SHIFT
), Capabilities
);
1624 Returns a map of the memory resources in the global coherency domain of the
1627 @param NumberOfDescriptors Number of descriptors.
1628 @param MemorySpaceMap Descriptor array
1630 @retval EFI_INVALID_PARAMETER Invalid parameter
1631 @retval EFI_OUT_OF_RESOURCES No enough buffer to allocate
1632 @retval EFI_SUCCESS Successfully get memory space map.
1637 CoreGetMemorySpaceMap (
1638 OUT UINTN
*NumberOfDescriptors
,
1639 OUT EFI_GCD_MEMORY_SPACE_DESCRIPTOR
**MemorySpaceMap
1644 EFI_GCD_MAP_ENTRY
*Entry
;
1645 EFI_GCD_MEMORY_SPACE_DESCRIPTOR
*Descriptor
;
1648 // Make sure parameters are valid
1650 if (NumberOfDescriptors
== NULL
) {
1651 return EFI_INVALID_PARAMETER
;
1653 if (MemorySpaceMap
== NULL
) {
1654 return EFI_INVALID_PARAMETER
;
1657 CoreAcquireGcdMemoryLock ();
1660 // Count the number of descriptors
1662 *NumberOfDescriptors
= CoreCountGcdMapEntry (&mGcdMemorySpaceMap
);
1665 // Allocate the MemorySpaceMap
1667 *MemorySpaceMap
= AllocatePool (*NumberOfDescriptors
* sizeof (EFI_GCD_MEMORY_SPACE_DESCRIPTOR
));
1668 if (*MemorySpaceMap
== NULL
) {
1669 Status
= EFI_OUT_OF_RESOURCES
;
1674 // Fill in the MemorySpaceMap
1676 Descriptor
= *MemorySpaceMap
;
1677 Link
= mGcdMemorySpaceMap
.ForwardLink
;
1678 while (Link
!= &mGcdMemorySpaceMap
) {
1679 Entry
= CR (Link
, EFI_GCD_MAP_ENTRY
, Link
, EFI_GCD_MAP_SIGNATURE
);
1680 BuildMemoryDescriptor (Descriptor
, Entry
);
1682 Link
= Link
->ForwardLink
;
1684 Status
= EFI_SUCCESS
;
1687 CoreReleaseGcdMemoryLock ();
1693 Adds reserved I/O or I/O resources to the global coherency domain of the processor.
1695 @param GcdIoType IO type of the segment.
1696 @param BaseAddress Base address of the segment.
1697 @param Length Length of the segment.
1699 @retval EFI_SUCCESS Merged this segment into GCD map.
1700 @retval EFI_INVALID_PARAMETER Parameter not valid
1706 IN EFI_GCD_IO_TYPE GcdIoType
,
1707 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
1711 DEBUG ((DEBUG_GCD
, "GCD:AddIoSpace(Base=%016lx,Length=%016lx)\n", BaseAddress
, Length
));
1712 DEBUG ((DEBUG_GCD
, " GcdIoType = %a\n", mGcdIoTypeNames
[MIN (GcdIoType
, EfiGcdIoTypeMaximum
)]));
1715 // Make sure parameters are valid
1717 if (GcdIoType
<= EfiGcdIoTypeNonExistent
|| GcdIoType
>= EfiGcdIoTypeMaximum
) {
1718 return EFI_INVALID_PARAMETER
;
1720 return CoreConvertSpace (GCD_ADD_IO_OPERATION
, (EFI_GCD_MEMORY_TYPE
) 0, GcdIoType
, BaseAddress
, Length
, 0, 0);
1725 Allocates nonexistent I/O, reserved I/O, or I/O resources from the global coherency
1726 domain of the processor.
1728 @param GcdAllocateType The type of allocate operation
1729 @param GcdIoType The desired IO type
1730 @param Alignment Align with 2^Alignment
1731 @param Length Length to allocate
1732 @param BaseAddress Base address to allocate
1733 @param ImageHandle The image handle consume the allocated space.
1734 @param DeviceHandle The device handle consume the allocated space.
1736 @retval EFI_INVALID_PARAMETER Invalid parameter.
1737 @retval EFI_NOT_FOUND No descriptor contains the desired space.
1738 @retval EFI_SUCCESS IO space successfully allocated.
1743 CoreAllocateIoSpace (
1744 IN EFI_GCD_ALLOCATE_TYPE GcdAllocateType
,
1745 IN EFI_GCD_IO_TYPE GcdIoType
,
1748 IN OUT EFI_PHYSICAL_ADDRESS
*BaseAddress
,
1749 IN EFI_HANDLE ImageHandle
,
1750 IN EFI_HANDLE DeviceHandle OPTIONAL
1753 DEBUG ((DEBUG_GCD
, "GCD:AllocateIoSpace(Base=%016lx,Length=%016lx)\n", *BaseAddress
, Length
));
1754 DEBUG ((DEBUG_GCD
, " GcdAllocateType = %a\n", mGcdAllocationTypeNames
[MIN (GcdAllocateType
, EfiGcdMaxAllocateType
)]));
1755 DEBUG ((DEBUG_GCD
, " GcdIoType = %a\n", mGcdIoTypeNames
[MIN (GcdIoType
, EfiGcdIoTypeMaximum
)]));
1756 DEBUG ((DEBUG_GCD
, " Alignment = %016lx\n", LShiftU64 (1, Alignment
)));
1757 DEBUG ((DEBUG_GCD
, " ImageHandle = %p\n", ImageHandle
));
1758 DEBUG ((DEBUG_GCD
, " DeviceHandle = %p\n", DeviceHandle
));
1760 return CoreAllocateSpace (
1761 GCD_ALLOCATE_IO_OPERATION
,
1763 (EFI_GCD_MEMORY_TYPE
) 0,
1775 Frees nonexistent I/O, reserved I/O, or I/O resources from the global coherency
1776 domain of the processor.
1778 @param BaseAddress Base address of the segment.
1779 @param Length Length of the segment.
1781 @retval EFI_SUCCESS Space successfully freed.
1787 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
1791 DEBUG ((DEBUG_GCD
, "GCD:FreeIoSpace(Base=%016lx,Length=%016lx)\n", BaseAddress
, Length
));
1793 return CoreConvertSpace (GCD_FREE_IO_OPERATION
, (EFI_GCD_MEMORY_TYPE
) 0, (EFI_GCD_IO_TYPE
) 0, BaseAddress
, Length
, 0, 0);
1798 Removes reserved I/O or I/O resources from the global coherency domain of the
1801 @param BaseAddress Base address of the segment.
1802 @param Length Length of the segment.
1804 @retval EFI_SUCCESS Successfully removed a segment of IO space.
1810 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
1814 DEBUG ((DEBUG_GCD
, "GCD:RemoveIoSpace(Base=%016lx,Length=%016lx)\n", BaseAddress
, Length
));
1816 return CoreConvertSpace (GCD_REMOVE_IO_OPERATION
, (EFI_GCD_MEMORY_TYPE
) 0, (EFI_GCD_IO_TYPE
) 0, BaseAddress
, Length
, 0, 0);
1821 Build a IO descriptor according to an entry.
1823 @param Descriptor The descriptor to be built
1824 @param Entry According to this entry
1829 IN EFI_GCD_IO_SPACE_DESCRIPTOR
*Descriptor
,
1830 IN EFI_GCD_MAP_ENTRY
*Entry
1833 Descriptor
->BaseAddress
= Entry
->BaseAddress
;
1834 Descriptor
->Length
= Entry
->EndAddress
- Entry
->BaseAddress
+ 1;
1835 Descriptor
->GcdIoType
= Entry
->GcdIoType
;
1836 Descriptor
->ImageHandle
= Entry
->ImageHandle
;
1837 Descriptor
->DeviceHandle
= Entry
->DeviceHandle
;
1842 Retrieves the descriptor for an I/O region containing a specified address.
1844 @param BaseAddress Specified start address
1845 @param Descriptor Specified length
1847 @retval EFI_INVALID_PARAMETER Descriptor is NULL.
1848 @retval EFI_SUCCESS Successfully get the IO space descriptor.
1853 CoreGetIoSpaceDescriptor (
1854 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
1855 OUT EFI_GCD_IO_SPACE_DESCRIPTOR
*Descriptor
1859 LIST_ENTRY
*StartLink
;
1860 LIST_ENTRY
*EndLink
;
1861 EFI_GCD_MAP_ENTRY
*Entry
;
1864 // Make sure parameters are valid
1866 if (Descriptor
== NULL
) {
1867 return EFI_INVALID_PARAMETER
;
1870 CoreAcquireGcdIoLock ();
1873 // Search for the list of descriptors that contain BaseAddress
1875 Status
= CoreSearchGcdMapEntry (BaseAddress
, 1, &StartLink
, &EndLink
, &mGcdIoSpaceMap
);
1876 if (EFI_ERROR (Status
)) {
1877 Status
= EFI_NOT_FOUND
;
1879 ASSERT (StartLink
!= NULL
&& EndLink
!= NULL
);
1881 // Copy the contents of the found descriptor into Descriptor
1883 Entry
= CR (StartLink
, EFI_GCD_MAP_ENTRY
, Link
, EFI_GCD_MAP_SIGNATURE
);
1884 BuildIoDescriptor (Descriptor
, Entry
);
1887 CoreReleaseGcdIoLock ();
1894 Returns a map of the I/O resources in the global coherency domain of the processor.
1896 @param NumberOfDescriptors Number of descriptors.
1897 @param IoSpaceMap Descriptor array
1899 @retval EFI_INVALID_PARAMETER Invalid parameter
1900 @retval EFI_OUT_OF_RESOURCES No enough buffer to allocate
1901 @retval EFI_SUCCESS Successfully get IO space map.
1907 OUT UINTN
*NumberOfDescriptors
,
1908 OUT EFI_GCD_IO_SPACE_DESCRIPTOR
**IoSpaceMap
1913 EFI_GCD_MAP_ENTRY
*Entry
;
1914 EFI_GCD_IO_SPACE_DESCRIPTOR
*Descriptor
;
1917 // Make sure parameters are valid
1919 if (NumberOfDescriptors
== NULL
) {
1920 return EFI_INVALID_PARAMETER
;
1922 if (IoSpaceMap
== NULL
) {
1923 return EFI_INVALID_PARAMETER
;
1926 CoreAcquireGcdIoLock ();
1929 // Count the number of descriptors
1931 *NumberOfDescriptors
= CoreCountGcdMapEntry (&mGcdIoSpaceMap
);
1934 // Allocate the IoSpaceMap
1936 *IoSpaceMap
= AllocatePool (*NumberOfDescriptors
* sizeof (EFI_GCD_IO_SPACE_DESCRIPTOR
));
1937 if (*IoSpaceMap
== NULL
) {
1938 Status
= EFI_OUT_OF_RESOURCES
;
1943 // Fill in the IoSpaceMap
1945 Descriptor
= *IoSpaceMap
;
1946 Link
= mGcdIoSpaceMap
.ForwardLink
;
1947 while (Link
!= &mGcdIoSpaceMap
) {
1948 Entry
= CR (Link
, EFI_GCD_MAP_ENTRY
, Link
, EFI_GCD_MAP_SIGNATURE
);
1949 BuildIoDescriptor (Descriptor
, Entry
);
1951 Link
= Link
->ForwardLink
;
1953 Status
= EFI_SUCCESS
;
1956 CoreReleaseGcdIoLock ();
1962 Converts a Resource Descriptor HOB attributes mask to an EFI Memory Descriptor
1965 @param GcdMemoryType Type of resource in the GCD memory map.
1966 @param Attributes The attribute mask in the Resource Descriptor
1969 @return The capabilities mask for an EFI Memory Descriptor.
1973 CoreConvertResourceDescriptorHobAttributesToCapabilities (
1974 EFI_GCD_MEMORY_TYPE GcdMemoryType
,
1978 UINT64 Capabilities
;
1979 GCD_ATTRIBUTE_CONVERSION_ENTRY
*Conversion
;
1982 // Convert the Resource HOB Attributes to an EFI Memory Capabilities mask
1984 for (Capabilities
= 0, Conversion
= mAttributeConversionTable
; Conversion
->Attribute
!= 0; Conversion
++) {
1985 if (Conversion
->Memory
|| (GcdMemoryType
!= EfiGcdMemoryTypeSystemMemory
)) {
1986 if (Attributes
& Conversion
->Attribute
) {
1987 Capabilities
|= Conversion
->Capability
;
1992 return Capabilities
;
1997 External function. Initializes memory services based on the memory
1998 descriptor HOBs. This function is responsible for priming the memory
1999 map, so memory allocations and resource allocations can be made.
2000 The first part of this function can not depend on any memory services
2001 until at least one memory descriptor is provided to the memory services.
2003 @param HobStart The start address of the HOB.
2004 @param MemoryBaseAddress Start address of memory region found to init DXE
2006 @param MemoryLength Length of memory region found to init DXE core.
2008 @retval EFI_SUCCESS Memory services successfully initialized.
2012 CoreInitializeMemoryServices (
2014 OUT EFI_PHYSICAL_ADDRESS
*MemoryBaseAddress
,
2015 OUT UINT64
*MemoryLength
2018 EFI_PEI_HOB_POINTERS Hob
;
2019 EFI_MEMORY_TYPE_INFORMATION
*EfiMemoryTypeInformation
;
2022 EFI_HOB_HANDOFF_INFO_TABLE
*PhitHob
;
2023 EFI_HOB_RESOURCE_DESCRIPTOR
*ResourceHob
;
2024 EFI_HOB_RESOURCE_DESCRIPTOR
*PhitResourceHob
;
2025 EFI_PHYSICAL_ADDRESS BaseAddress
;
2028 UINT64 Capabilities
;
2029 EFI_PHYSICAL_ADDRESS MaxMemoryBaseAddress
;
2030 UINT64 MaxMemoryLength
;
2031 UINT64 MaxMemoryAttributes
;
2032 EFI_PHYSICAL_ADDRESS TestedMemoryBaseAddress
;
2033 UINT64 TestedMemoryLength
;
2034 EFI_PHYSICAL_ADDRESS HighAddress
;
2035 EFI_HOB_GUID_TYPE
*GuidHob
;
2036 UINT32 ReservedCodePageNumber
;
2039 // Point at the first HOB. This must be the PHIT HOB.
2041 Hob
.Raw
= *HobStart
;
2042 ASSERT (GET_HOB_TYPE (Hob
) == EFI_HOB_TYPE_HANDOFF
);
2045 // Initialize the spin locks and maps in the memory services.
2046 // Also fill in the memory services into the EFI Boot Services Table
2048 CoreInitializePool ();
2051 // Initialize Local Variables
2053 PhitResourceHob
= NULL
;
2058 MaxMemoryBaseAddress
= 0;
2059 MaxMemoryLength
= 0;
2060 MaxMemoryAttributes
= 0;
2063 // Cache the PHIT HOB for later use
2065 PhitHob
= Hob
.HandoffInformationTable
;
2067 if (PcdGet64(PcdLoadModuleAtFixAddressEnable
) != 0) {
2068 ReservedCodePageNumber
= PcdGet32(PcdLoadFixAddressRuntimeCodePageNumber
);
2069 ReservedCodePageNumber
+= PcdGet32(PcdLoadFixAddressBootTimeCodePageNumber
);
2072 // cache the Top address for loading modules at Fixed Address
2074 gLoadModuleAtFixAddressConfigurationTable
.DxeCodeTopAddress
= PhitHob
->EfiMemoryTop
2075 + EFI_PAGES_TO_SIZE(ReservedCodePageNumber
);
2078 // See if a Memory Type Information HOB is available
2080 GuidHob
= GetFirstGuidHob (&gEfiMemoryTypeInformationGuid
);
2081 if (GuidHob
!= NULL
) {
2082 EfiMemoryTypeInformation
= GET_GUID_HOB_DATA (GuidHob
);
2083 DataSize
= GET_GUID_HOB_DATA_SIZE (GuidHob
);
2084 if (EfiMemoryTypeInformation
!= NULL
&& DataSize
> 0 && DataSize
<= (EfiMaxMemoryType
+ 1) * sizeof (EFI_MEMORY_TYPE_INFORMATION
)) {
2085 CopyMem (&gMemoryTypeInformation
, EfiMemoryTypeInformation
, DataSize
);
2090 // Find the Resource Descriptor HOB that contains PHIT range EfiFreeMemoryBottom..EfiFreeMemoryTop
2094 for (Hob
.Raw
= *HobStart
; !END_OF_HOB_LIST(Hob
); Hob
.Raw
= GET_NEXT_HOB(Hob
)) {
2096 // Skip all HOBs except Resource Descriptor HOBs
2098 if (GET_HOB_TYPE (Hob
) != EFI_HOB_TYPE_RESOURCE_DESCRIPTOR
) {
2103 // Skip Resource Descriptor HOBs that do not describe tested system memory
2105 ResourceHob
= Hob
.ResourceDescriptor
;
2106 if (ResourceHob
->ResourceType
!= EFI_RESOURCE_SYSTEM_MEMORY
) {
2109 if ((ResourceHob
->ResourceAttribute
& MEMORY_ATTRIBUTE_MASK
) != TESTED_MEMORY_ATTRIBUTES
) {
2114 // Skip Resource Descriptor HOBs that do not contain the PHIT range EfiFreeMemoryBottom..EfiFreeMemoryTop
2116 if (PhitHob
->EfiFreeMemoryBottom
< ResourceHob
->PhysicalStart
) {
2119 if (PhitHob
->EfiFreeMemoryTop
> (ResourceHob
->PhysicalStart
+ ResourceHob
->ResourceLength
)) {
2124 // Cache the resource descriptor HOB for the memory region described by the PHIT HOB
2126 PhitResourceHob
= ResourceHob
;
2130 // Compute range between PHIT EfiFreeMemoryTop and the end of the Resource Descriptor HOB
2132 Attributes
= PhitResourceHob
->ResourceAttribute
;
2133 BaseAddress
= PageAlignAddress (PhitHob
->EfiMemoryTop
);
2134 Length
= PageAlignLength (ResourceHob
->PhysicalStart
+ ResourceHob
->ResourceLength
- BaseAddress
);
2135 if (Length
< MINIMUM_INITIAL_MEMORY_SIZE
) {
2137 // If that range is not large enough to intialize the DXE Core, then
2138 // Compute range between PHIT EfiFreeMemoryBottom and PHIT EfiFreeMemoryTop
2140 BaseAddress
= PageAlignAddress (PhitHob
->EfiFreeMemoryBottom
);
2141 Length
= PageAlignLength (PhitHob
->EfiFreeMemoryTop
- BaseAddress
);
2142 if (Length
< MINIMUM_INITIAL_MEMORY_SIZE
) {
2144 // If that range is not large enough to intialize the DXE Core, then
2145 // Compute range between the start of the Resource Descriptor HOB and the start of the HOB List
2147 BaseAddress
= PageAlignAddress (ResourceHob
->PhysicalStart
);
2148 Length
= PageAlignLength ((UINT64
)((UINTN
)*HobStart
- BaseAddress
));
2155 // Assert if a resource descriptor HOB for the memory region described by the PHIT was not found
2160 // Search all the resource descriptor HOBs from the highest possible addresses down for a memory
2161 // region that is big enough to initialize the DXE core. Always skip the PHIT Resource HOB.
2162 // The max address must be within the physically addressible range for the processor.
2164 HighAddress
= MAX_ADDRESS
;
2165 for (Hob
.Raw
= *HobStart
; !END_OF_HOB_LIST(Hob
); Hob
.Raw
= GET_NEXT_HOB(Hob
)) {
2167 // Skip the Resource Descriptor HOB that contains the PHIT
2169 if (Hob
.ResourceDescriptor
== PhitResourceHob
) {
2173 // Skip all HOBs except Resource Descriptor HOBs
2175 if (GET_HOB_TYPE (Hob
) != EFI_HOB_TYPE_RESOURCE_DESCRIPTOR
) {
2180 // Skip Resource Descriptor HOBs that do not describe tested system memory below MAX_ADDRESS
2182 ResourceHob
= Hob
.ResourceDescriptor
;
2183 if (ResourceHob
->ResourceType
!= EFI_RESOURCE_SYSTEM_MEMORY
) {
2186 if ((ResourceHob
->ResourceAttribute
& MEMORY_ATTRIBUTE_MASK
) != TESTED_MEMORY_ATTRIBUTES
) {
2189 if ((ResourceHob
->PhysicalStart
+ ResourceHob
->ResourceLength
) > (EFI_PHYSICAL_ADDRESS
)MAX_ADDRESS
) {
2194 // Skip Resource Descriptor HOBs that are below a previously found Resource Descriptor HOB
2196 if (HighAddress
!= (EFI_PHYSICAL_ADDRESS
)MAX_ADDRESS
&& ResourceHob
->PhysicalStart
<= HighAddress
) {
2201 // Skip Resource Descriptor HOBs that are not large enough to initilize the DXE Core
2203 TestedMemoryBaseAddress
= PageAlignAddress (ResourceHob
->PhysicalStart
);
2204 TestedMemoryLength
= PageAlignLength (ResourceHob
->PhysicalStart
+ ResourceHob
->ResourceLength
- TestedMemoryBaseAddress
);
2205 if (TestedMemoryLength
< MINIMUM_INITIAL_MEMORY_SIZE
) {
2210 // Save the Resource Descriptor HOB context that is large enough to initilize the DXE Core
2212 MaxMemoryBaseAddress
= TestedMemoryBaseAddress
;
2213 MaxMemoryLength
= TestedMemoryLength
;
2214 MaxMemoryAttributes
= ResourceHob
->ResourceAttribute
;
2215 HighAddress
= ResourceHob
->PhysicalStart
;
2219 // If Length is not large enough to initialize the DXE Core or a Resource
2220 // Descriptor HOB was found above the PHIT HOB that is large enough to initialize
2221 // the DXE Core, then use the range described by the Resource Descriptor
2222 // HOB that was found above the PHIT HOB.
2224 if ((Length
< MINIMUM_INITIAL_MEMORY_SIZE
) ||
2225 (MaxMemoryBaseAddress
> BaseAddress
&& MaxMemoryLength
>= MINIMUM_INITIAL_MEMORY_SIZE
)) {
2226 BaseAddress
= MaxMemoryBaseAddress
;
2227 Length
= MaxMemoryLength
;
2228 Attributes
= MaxMemoryAttributes
;
2232 // If no memory regions are found that are big enough to initialize the DXE core, then ASSERT().
2234 ASSERT (Length
>= MINIMUM_INITIAL_MEMORY_SIZE
);
2237 // Convert the Resource HOB Attributes to an EFI Memory Capabilities mask
2239 Capabilities
= CoreConvertResourceDescriptorHobAttributesToCapabilities (EfiGcdMemoryTypeSystemMemory
, Attributes
);
2242 // Declare the very first memory region, so the EFI Memory Services are available.
2244 CoreAddMemoryDescriptor (
2245 EfiConventionalMemory
,
2247 RShiftU64 (Length
, EFI_PAGE_SHIFT
),
2251 *MemoryBaseAddress
= BaseAddress
;
2252 *MemoryLength
= Length
;
2259 External function. Initializes the GCD and memory services based on the memory
2260 descriptor HOBs. This function is responsible for priming the GCD map and the
2261 memory map, so memory allocations and resource allocations can be made. The
2262 HobStart will be relocated to a pool buffer.
2264 @param HobStart The start address of the HOB
2265 @param MemoryBaseAddress Start address of memory region found to init DXE
2267 @param MemoryLength Length of memory region found to init DXE core.
2269 @retval EFI_SUCCESS GCD services successfully initialized.
2273 CoreInitializeGcdServices (
2274 IN OUT VOID
**HobStart
,
2275 IN EFI_PHYSICAL_ADDRESS MemoryBaseAddress
,
2276 IN UINT64 MemoryLength
2279 EFI_PEI_HOB_POINTERS Hob
;
2281 EFI_HOB_HANDOFF_INFO_TABLE
*PhitHob
;
2282 UINT8 SizeOfMemorySpace
;
2283 UINT8 SizeOfIoSpace
;
2284 EFI_HOB_RESOURCE_DESCRIPTOR
*ResourceHob
;
2285 EFI_PHYSICAL_ADDRESS BaseAddress
;
2288 EFI_GCD_MAP_ENTRY
*Entry
;
2289 EFI_GCD_MEMORY_TYPE GcdMemoryType
;
2290 EFI_GCD_IO_TYPE GcdIoType
;
2291 EFI_GCD_MEMORY_SPACE_DESCRIPTOR Descriptor
;
2292 EFI_HOB_MEMORY_ALLOCATION
*MemoryHob
;
2293 EFI_HOB_FIRMWARE_VOLUME
*FirmwareVolumeHob
;
2294 UINTN NumberOfDescriptors
;
2295 EFI_GCD_MEMORY_SPACE_DESCRIPTOR
*MemorySpaceMap
;
2297 UINT64 Capabilities
;
2298 EFI_HOB_CPU
* CpuHob
;
2301 // Cache the PHIT HOB for later use
2303 PhitHob
= (EFI_HOB_HANDOFF_INFO_TABLE
*)(*HobStart
);
2306 // Get the number of address lines in the I/O and Memory space for the CPU
2308 CpuHob
= GetFirstHob (EFI_HOB_TYPE_CPU
);
2309 ASSERT (CpuHob
!= NULL
);
2310 SizeOfMemorySpace
= CpuHob
->SizeOfMemorySpace
;
2311 SizeOfIoSpace
= CpuHob
->SizeOfIoSpace
;
2314 // Initialize the GCD Memory Space Map
2316 Entry
= AllocateCopyPool (sizeof (EFI_GCD_MAP_ENTRY
), &mGcdMemorySpaceMapEntryTemplate
);
2317 ASSERT (Entry
!= NULL
);
2319 Entry
->EndAddress
= LShiftU64 (1, SizeOfMemorySpace
) - 1;
2321 InsertHeadList (&mGcdMemorySpaceMap
, &Entry
->Link
);
2323 CoreDumpGcdMemorySpaceMap (TRUE
);
2326 // Initialize the GCD I/O Space Map
2328 Entry
= AllocateCopyPool (sizeof (EFI_GCD_MAP_ENTRY
), &mGcdIoSpaceMapEntryTemplate
);
2329 ASSERT (Entry
!= NULL
);
2331 Entry
->EndAddress
= LShiftU64 (1, SizeOfIoSpace
) - 1;
2333 InsertHeadList (&mGcdIoSpaceMap
, &Entry
->Link
);
2335 CoreDumpGcdIoSpaceMap (TRUE
);
2338 // Walk the HOB list and add all resource descriptors to the GCD
2340 for (Hob
.Raw
= *HobStart
; !END_OF_HOB_LIST(Hob
); Hob
.Raw
= GET_NEXT_HOB(Hob
)) {
2342 GcdMemoryType
= EfiGcdMemoryTypeNonExistent
;
2343 GcdIoType
= EfiGcdIoTypeNonExistent
;
2345 if (GET_HOB_TYPE (Hob
) == EFI_HOB_TYPE_RESOURCE_DESCRIPTOR
) {
2347 ResourceHob
= Hob
.ResourceDescriptor
;
2349 switch (ResourceHob
->ResourceType
) {
2350 case EFI_RESOURCE_SYSTEM_MEMORY
:
2351 if ((ResourceHob
->ResourceAttribute
& MEMORY_ATTRIBUTE_MASK
) == TESTED_MEMORY_ATTRIBUTES
) {
2352 GcdMemoryType
= EfiGcdMemoryTypeSystemMemory
;
2354 if ((ResourceHob
->ResourceAttribute
& MEMORY_ATTRIBUTE_MASK
) == INITIALIZED_MEMORY_ATTRIBUTES
) {
2355 GcdMemoryType
= EfiGcdMemoryTypeReserved
;
2357 if ((ResourceHob
->ResourceAttribute
& MEMORY_ATTRIBUTE_MASK
) == PRESENT_MEMORY_ATTRIBUTES
) {
2358 GcdMemoryType
= EfiGcdMemoryTypeReserved
;
2361 case EFI_RESOURCE_MEMORY_MAPPED_IO
:
2362 case EFI_RESOURCE_FIRMWARE_DEVICE
:
2363 GcdMemoryType
= EfiGcdMemoryTypeMemoryMappedIo
;
2365 case EFI_RESOURCE_MEMORY_MAPPED_IO_PORT
:
2366 case EFI_RESOURCE_MEMORY_RESERVED
:
2367 GcdMemoryType
= EfiGcdMemoryTypeReserved
;
2369 case EFI_RESOURCE_IO
:
2370 GcdIoType
= EfiGcdIoTypeIo
;
2372 case EFI_RESOURCE_IO_RESERVED
:
2373 GcdIoType
= EfiGcdIoTypeReserved
;
2377 if (GcdMemoryType
!= EfiGcdMemoryTypeNonExistent
) {
2379 // Validate the Resource HOB Attributes
2381 CoreValidateResourceDescriptorHobAttributes (ResourceHob
->ResourceAttribute
);
2384 // Convert the Resource HOB Attributes to an EFI Memory Capabilities mask
2386 Capabilities
= CoreConvertResourceDescriptorHobAttributesToCapabilities (
2388 ResourceHob
->ResourceAttribute
2391 Status
= CoreInternalAddMemorySpace (
2393 ResourceHob
->PhysicalStart
,
2394 ResourceHob
->ResourceLength
,
2399 if (GcdIoType
!= EfiGcdIoTypeNonExistent
) {
2400 Status
= CoreAddIoSpace (
2402 ResourceHob
->PhysicalStart
,
2403 ResourceHob
->ResourceLength
2410 // Allocate first memory region from the GCD by the DXE core
2412 Status
= CoreAllocateMemorySpace (
2413 EfiGcdAllocateAddress
,
2414 EfiGcdMemoryTypeSystemMemory
,
2418 gDxeCoreImageHandle
,
2423 // Walk the HOB list and allocate all memory space that is consumed by memory allocation HOBs,
2424 // and Firmware Volume HOBs. Also update the EFI Memory Map with the memory allocation HOBs.
2426 for (Hob
.Raw
= *HobStart
; !END_OF_HOB_LIST(Hob
); Hob
.Raw
= GET_NEXT_HOB(Hob
)) {
2427 if (GET_HOB_TYPE (Hob
) == EFI_HOB_TYPE_MEMORY_ALLOCATION
) {
2428 MemoryHob
= Hob
.MemoryAllocation
;
2429 BaseAddress
= MemoryHob
->AllocDescriptor
.MemoryBaseAddress
;
2430 Status
= CoreGetMemorySpaceDescriptor (BaseAddress
, &Descriptor
);
2431 if (!EFI_ERROR (Status
)) {
2432 Status
= CoreAllocateMemorySpace (
2433 EfiGcdAllocateAddress
,
2434 Descriptor
.GcdMemoryType
,
2436 MemoryHob
->AllocDescriptor
.MemoryLength
,
2438 gDxeCoreImageHandle
,
2441 if (!EFI_ERROR (Status
) && Descriptor
.GcdMemoryType
== EfiGcdMemoryTypeSystemMemory
) {
2442 CoreAddMemoryDescriptor (
2443 MemoryHob
->AllocDescriptor
.MemoryType
,
2444 MemoryHob
->AllocDescriptor
.MemoryBaseAddress
,
2445 RShiftU64 (MemoryHob
->AllocDescriptor
.MemoryLength
, EFI_PAGE_SHIFT
),
2446 Descriptor
.Capabilities
& (~EFI_MEMORY_RUNTIME
)
2452 if (GET_HOB_TYPE (Hob
) == EFI_HOB_TYPE_FV
) {
2453 FirmwareVolumeHob
= Hob
.FirmwareVolume
;
2454 BaseAddress
= FirmwareVolumeHob
->BaseAddress
;
2455 Status
= CoreAllocateMemorySpace (
2456 EfiGcdAllocateAddress
,
2457 EfiGcdMemoryTypeMemoryMappedIo
,
2459 FirmwareVolumeHob
->Length
,
2461 gDxeCoreImageHandle
,
2468 // Relocate HOB List to an allocated pool buffer.
2470 NewHobList
= AllocateCopyPool (
2471 (UINTN
)PhitHob
->EfiFreeMemoryBottom
- (UINTN
)(*HobStart
),
2474 ASSERT (NewHobList
!= NULL
);
2476 *HobStart
= NewHobList
;
2477 gHobList
= NewHobList
;
2480 // Add and allocate the remaining unallocated system memory to the memory services.
2482 Status
= CoreGetMemorySpaceMap (&NumberOfDescriptors
, &MemorySpaceMap
);
2483 ASSERT (Status
== EFI_SUCCESS
);
2485 for (Index
= 0; Index
< NumberOfDescriptors
; Index
++) {
2486 if (MemorySpaceMap
[Index
].GcdMemoryType
== EfiGcdMemoryTypeSystemMemory
) {
2487 if (MemorySpaceMap
[Index
].ImageHandle
== NULL
) {
2488 BaseAddress
= PageAlignAddress (MemorySpaceMap
[Index
].BaseAddress
);
2489 Length
= PageAlignLength (MemorySpaceMap
[Index
].BaseAddress
+ MemorySpaceMap
[Index
].Length
- BaseAddress
);
2490 if (Length
== 0 || MemorySpaceMap
[Index
].BaseAddress
+ MemorySpaceMap
[Index
].Length
< BaseAddress
) {
2493 CoreAddMemoryDescriptor (
2494 EfiConventionalMemory
,
2496 RShiftU64 (Length
, EFI_PAGE_SHIFT
),
2497 MemorySpaceMap
[Index
].Capabilities
& (~EFI_MEMORY_RUNTIME
)
2499 Status
= CoreAllocateMemorySpace (
2500 EfiGcdAllocateAddress
,
2501 EfiGcdMemoryTypeSystemMemory
,
2505 gDxeCoreImageHandle
,
2511 CoreFreePool (MemorySpaceMap
);