3 Copyright (c) 2006, Intel Corporation
4 All rights reserved. This program and the accompanying materials
5 are licensed and made available under the terms and conditions of the BSD License
6 which accompanies this distribution. The full text of the license may be found at
7 http://opensource.org/licenses/bsd-license.php
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
17 The file contains the GCD related services in the EFI Boot Services Table.
18 The GCD services are used to manage the memory and I/O regions that
19 are accessible to the CPU that is executing the DXE core.
25 #define MINIMUM_INITIAL_MEMORY_SIZE 0x10000
27 #define MEMORY_ATTRIBUTE_MASK (EFI_RESOURCE_ATTRIBUTE_PRESENT | \
28 EFI_RESOURCE_ATTRIBUTE_INITIALIZED | \
29 EFI_RESOURCE_ATTRIBUTE_TESTED | \
30 EFI_RESOURCE_ATTRIBUTE_READ_PROTECTED | \
31 EFI_RESOURCE_ATTRIBUTE_WRITE_PROTECTED | \
32 EFI_RESOURCE_ATTRIBUTE_EXECUTION_PROTECTED | \
33 EFI_RESOURCE_ATTRIBUTE_16_BIT_IO | \
34 EFI_RESOURCE_ATTRIBUTE_32_BIT_IO | \
35 EFI_RESOURCE_ATTRIBUTE_64_BIT_IO )
37 #define TESTED_MEMORY_ATTRIBUTES (EFI_RESOURCE_ATTRIBUTE_PRESENT | \
38 EFI_RESOURCE_ATTRIBUTE_INITIALIZED | \
39 EFI_RESOURCE_ATTRIBUTE_TESTED )
41 #define INITIALIZED_MEMORY_ATTRIBUTES (EFI_RESOURCE_ATTRIBUTE_PRESENT | \
42 EFI_RESOURCE_ATTRIBUTE_INITIALIZED )
44 #define PRESENT_MEMORY_ATTRIBUTES (EFI_RESOURCE_ATTRIBUTE_PRESENT)
46 #define INVALID_CPU_ARCH_ATTRIBUTES 0xffffffff
51 EFI_LOCK mGcdMemorySpaceLock
= EFI_INITIALIZE_LOCK_VARIABLE (EFI_TPL_NOTIFY
);
52 EFI_LOCK mGcdIoSpaceLock
= EFI_INITIALIZE_LOCK_VARIABLE (EFI_TPL_NOTIFY
);
53 LIST_ENTRY mGcdMemorySpaceMap
= INITIALIZE_LIST_HEAD_VARIABLE (mGcdMemorySpaceMap
);
54 LIST_ENTRY mGcdIoSpaceMap
= INITIALIZE_LIST_HEAD_VARIABLE (mGcdIoSpaceMap
);
56 EFI_GCD_MAP_ENTRY mGcdMemorySpaceMapEntryTemplate
= {
57 EFI_GCD_MAP_SIGNATURE
,
63 EfiGcdMemoryTypeNonExistent
,
69 EFI_GCD_MAP_ENTRY mGcdIoSpaceMapEntryTemplate
= {
70 EFI_GCD_MAP_SIGNATURE
,
76 (EFI_GCD_MEMORY_TYPE
) 0,
77 EfiGcdIoTypeNonExistent
,
82 GCD_ATTRIBUTE_CONVERSION_ENTRY mAttributeConversionTable
[] = {
83 { EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE
, EFI_MEMORY_UC
, TRUE
},
84 { EFI_RESOURCE_ATTRIBUTE_UNCACHED_EXPORTED
, EFI_MEMORY_UCE
, TRUE
},
85 { EFI_RESOURCE_ATTRIBUTE_WRITE_COMBINEABLE
, EFI_MEMORY_WC
, TRUE
},
86 { EFI_RESOURCE_ATTRIBUTE_WRITE_THROUGH_CACHEABLE
, EFI_MEMORY_WT
, TRUE
},
87 { EFI_RESOURCE_ATTRIBUTE_WRITE_BACK_CACHEABLE
, EFI_MEMORY_WB
, TRUE
},
88 { EFI_RESOURCE_ATTRIBUTE_READ_PROTECTED
, EFI_MEMORY_RP
, TRUE
},
89 { EFI_RESOURCE_ATTRIBUTE_WRITE_PROTECTED
, EFI_MEMORY_WP
, TRUE
},
90 { EFI_RESOURCE_ATTRIBUTE_EXECUTION_PROTECTED
, EFI_MEMORY_XP
, TRUE
},
91 { EFI_RESOURCE_ATTRIBUTE_PRESENT
, EFI_MEMORY_PRESENT
, FALSE
},
92 { EFI_RESOURCE_ATTRIBUTE_INITIALIZED
, EFI_MEMORY_INITIALIZED
, FALSE
},
93 { EFI_RESOURCE_ATTRIBUTE_TESTED
, EFI_MEMORY_TESTED
, FALSE
},
98 CoreAcquireGcdMemoryLock (
104 Acquire memory lock on mGcdMemorySpaceLock
114 CoreAcquireLock (&mGcdMemorySpaceLock
);
119 CoreReleaseGcdMemoryLock (
125 Release memory lock on mGcdMemorySpaceLock
135 CoreReleaseLock (&mGcdMemorySpaceLock
);
141 CoreAcquireGcdIoLock (
147 Acquire memory lock on mGcdIoSpaceLock
157 CoreAcquireLock (&mGcdIoSpaceLock
);
162 CoreReleaseGcdIoLock (
168 Release memory lock on mGcdIoSpaceLock
178 CoreReleaseLock (&mGcdIoSpaceLock
);
184 // GCD Initialization Worker Functions
197 Aligns a value to the specified boundary.
201 Value - 64 bit value to align
202 Alignment - Log base 2 of the boundary to align Value to
203 RoundUp - TRUE if Value is to be rounded up to the nearest aligned boundary.
204 FALSE is Value is to be rounded down to the nearest aligned boundary.
208 A 64 bit value is the aligned to the value nearest Value with an alignment by Alignment.
212 UINT64 AlignmentMask
;
214 AlignmentMask
= LShiftU64 (1, Alignment
) - 1;
216 Value
+= AlignmentMask
;
218 return Value
& (~AlignmentMask
);
230 Aligns address to the page boundary.
234 Value - 64 bit address to align
238 A 64 bit value is the aligned to the value nearest Value with an alignment by Alignment.
242 return AlignValue (Value
, EFI_PAGE_SHIFT
, TRUE
);
254 Aligns length to the page boundary.
258 Value - 64 bit length to align
262 A 64 bit value is the aligned to the value nearest Value with an alignment by Alignment.
266 return AlignValue (Value
, EFI_PAGE_SHIFT
, FALSE
);
270 // GCD Memory Space Worker Functions
274 CoreAllocateGcdMapEntry (
275 IN OUT EFI_GCD_MAP_ENTRY
**TopEntry
,
276 IN OUT EFI_GCD_MAP_ENTRY
**BottomEntry
282 Allocate pool for two entries.
286 TopEntry - An entry of GCD map
287 BottomEntry - An entry of GCD map
291 EFI_OUT_OF_RESOURCES - No enough buffer to be allocated.
292 EFI_SUCCESS - Both entries successfully allocated.
296 *TopEntry
= CoreAllocateZeroBootServicesPool (sizeof (EFI_GCD_MAP_ENTRY
));
297 if (*TopEntry
== NULL
) {
298 return EFI_OUT_OF_RESOURCES
;
301 *BottomEntry
= CoreAllocateZeroBootServicesPool (sizeof (EFI_GCD_MAP_ENTRY
));
302 if (*BottomEntry
== NULL
) {
303 CoreFreePool (*TopEntry
);
304 return EFI_OUT_OF_RESOURCES
;
312 CoreInsertGcdMapEntry (
314 IN EFI_GCD_MAP_ENTRY
*Entry
,
315 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
317 IN EFI_GCD_MAP_ENTRY
*TopEntry
,
318 IN EFI_GCD_MAP_ENTRY
*BottomEntry
324 Internal function. Inserts a new descriptor into a sorted list
328 Link - The linked list to insert the range BaseAddress and Length into
330 Entry - A pointer to the entry that is inserted
332 BaseAddress - The base address of the new range
334 Length - The length of the new range in bytes
336 TopEntry - Top pad entry to insert if needed.
338 BottomEntry - Bottom pad entry to insert if needed.
342 EFI_SUCCESS - The new range was inserted into the linked list
346 ASSERT (Length
!= 0);
347 ASSERT (TopEntry
->Signature
== 0);
348 ASSERT (BottomEntry
->Signature
== 0);
350 if (BaseAddress
> Entry
->BaseAddress
) {
351 CopyMem (BottomEntry
, Entry
, sizeof (EFI_GCD_MAP_ENTRY
));
352 Entry
->BaseAddress
= BaseAddress
;
353 BottomEntry
->EndAddress
= BaseAddress
- 1;
354 InsertTailList (Link
, &BottomEntry
->Link
);
357 if ((BaseAddress
+ Length
- 1) < Entry
->EndAddress
) {
358 CopyMem (TopEntry
, Entry
, sizeof (EFI_GCD_MAP_ENTRY
));
359 TopEntry
->BaseAddress
= BaseAddress
+ Length
;
360 Entry
->EndAddress
= BaseAddress
+ Length
- 1;
361 InsertHeadList (Link
, &TopEntry
->Link
);
369 CoreMergeGcdMapEntry (
378 Merge the Gcd region specified by Link and its adjacent entry
382 Link - Specify the entry to be merged (with its adjacent entry).
384 Forward - Direction (forward or backward).
390 EFI_SUCCESS - Successfully returned.
392 EFI_UNSUPPORTED - These adjacent regions could not merge.
396 LIST_ENTRY
*AdjacentLink
;
397 EFI_GCD_MAP_ENTRY
*Entry
;
398 EFI_GCD_MAP_ENTRY
*AdjacentEntry
;
401 // Get adjacent entry
404 AdjacentLink
= Link
->ForwardLink
;
406 AdjacentLink
= Link
->BackLink
;
410 // If AdjacentLink is the head of the list, then no merge can be performed
412 if (AdjacentLink
== Map
) {
416 Entry
= CR (Link
, EFI_GCD_MAP_ENTRY
, Link
, EFI_GCD_MAP_SIGNATURE
);
417 AdjacentEntry
= CR (AdjacentLink
, EFI_GCD_MAP_ENTRY
, Link
, EFI_GCD_MAP_SIGNATURE
);
419 if (Entry
->Capabilities
!= AdjacentEntry
->Capabilities
) {
420 return EFI_UNSUPPORTED
;
422 if (Entry
->Attributes
!= AdjacentEntry
->Attributes
) {
423 return EFI_UNSUPPORTED
;
425 if (Entry
->GcdMemoryType
!= AdjacentEntry
->GcdMemoryType
) {
426 return EFI_UNSUPPORTED
;
428 if (Entry
->GcdIoType
!= AdjacentEntry
->GcdIoType
) {
429 return EFI_UNSUPPORTED
;
431 if (Entry
->ImageHandle
!= AdjacentEntry
->ImageHandle
) {
432 return EFI_UNSUPPORTED
;
434 if (Entry
->DeviceHandle
!= AdjacentEntry
->DeviceHandle
) {
435 return EFI_UNSUPPORTED
;
439 Entry
->EndAddress
= AdjacentEntry
->EndAddress
;
441 Entry
->BaseAddress
= AdjacentEntry
->BaseAddress
;
443 RemoveEntryList (AdjacentLink
);
444 CoreFreePool (AdjacentEntry
);
451 CoreCleanupGcdMapEntry (
452 IN EFI_GCD_MAP_ENTRY
*TopEntry
,
453 IN EFI_GCD_MAP_ENTRY
*BottomEntry
,
454 IN LIST_ENTRY
*StartLink
,
455 IN LIST_ENTRY
*EndLink
,
462 Merge adjacent entries on total chain.
466 TopEntry - Top entry of GCD map.
468 BottomEntry - Bottom entry of GCD map.
470 StartLink - Start link of the list for this loop.
472 EndLink - End link of the list for this loop.
478 EFI_SUCCESS - GCD map successfully cleaned up.
484 if (TopEntry
->Signature
== 0) {
485 CoreFreePool (TopEntry
);
487 if (BottomEntry
->Signature
== 0) {
488 CoreFreePool (BottomEntry
);
492 while (Link
!= EndLink
->ForwardLink
) {
493 CoreMergeGcdMapEntry (Link
, FALSE
, Map
);
494 Link
= Link
->ForwardLink
;
496 CoreMergeGcdMapEntry (EndLink
, TRUE
, Map
);
503 CoreSearchGcdMapEntry (
504 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
506 OUT LIST_ENTRY
**StartLink
,
507 OUT LIST_ENTRY
**EndLink
,
514 Search a segment of memory space in GCD map. The result is a range of GCD entry list.
518 BaseAddress - The start address of the segment.
520 Length - The length of the segment.
522 StartLink - The first GCD entry involves this segment of memory space.
524 EndLink - The first GCD entry involves this segment of memory space.
526 Map - Points to the start entry to search.
530 EFI_SUCCESS - Successfully found the entry.
532 EFI_NOT_FOUND - Not found.
537 EFI_GCD_MAP_ENTRY
*Entry
;
539 ASSERT (Length
!= 0);
544 Link
= Map
->ForwardLink
;
545 while (Link
!= Map
) {
546 Entry
= CR (Link
, EFI_GCD_MAP_ENTRY
, Link
, EFI_GCD_MAP_SIGNATURE
);
547 if (BaseAddress
>= Entry
->BaseAddress
&& BaseAddress
<= Entry
->EndAddress
) {
550 if (*StartLink
!= NULL
) {
551 if ((BaseAddress
+ Length
- 1) >= Entry
->BaseAddress
&&
552 (BaseAddress
+ Length
- 1) <= Entry
->EndAddress
) {
557 Link
= Link
->ForwardLink
;
559 return EFI_NOT_FOUND
;
564 CoreCountGcdMapEntry (
571 Count the amount of GCD map entries.
575 Map - Points to the start entry to do the count loop.
587 Link
= Map
->ForwardLink
;
588 while (Link
!= Map
) {
590 Link
= Link
->ForwardLink
;
598 ConverToCpuArchAttributes (
605 Return the memory attribute specified by Attributes
609 Attributes - A num with some attribute bits on.
613 The enum value of memory attribute.
617 if ( (Attributes
& EFI_MEMORY_UC
) == EFI_MEMORY_UC
) {
618 return EFI_MEMORY_UC
;
621 if ( (Attributes
& EFI_MEMORY_WC
) == EFI_MEMORY_WC
) {
622 return EFI_MEMORY_WC
;
625 if ( (Attributes
& EFI_MEMORY_WT
) == EFI_MEMORY_WT
) {
626 return EFI_MEMORY_WT
;
629 if ( (Attributes
& EFI_MEMORY_WB
) == EFI_MEMORY_WB
) {
630 return EFI_MEMORY_WB
;
633 if ( (Attributes
& EFI_MEMORY_WP
) == EFI_MEMORY_WP
) {
634 return EFI_MEMORY_WP
;
637 return INVALID_CPU_ARCH_ATTRIBUTES
;
645 IN EFI_GCD_MEMORY_TYPE GcdMemoryType
,
646 IN EFI_GCD_IO_TYPE GcdIoType
,
647 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
649 IN UINT64 Capabilities
,
656 Do operation on a segment of memory space specified (add, free, remove, change attribute ...).
660 Operation - The type of the operation
662 GcdMemoryType - Additional information for the operation
664 GcdIoType - Additional information for the operation
666 BaseAddress - Start address of the segment
668 Length - length of the segment
670 Capabilities - The alterable attributes of a newly added entry
672 Attributes - The attributes needs to be set
676 EFI_INVALID_PARAMETER - Length is 0 or address (length) not aligned when setting attribute.
678 EFI_SUCCESS - Action successfully done.
680 EFI_UNSUPPORTED - Could not find the proper descriptor on this segment or
681 set an upsupported attribute.
683 EFI_ACCESS_DENIED - Operate on an space non-exist or is used for an image.
685 EFI_NOT_FOUND - Free a non-using space or remove a non-exist space, and so on.
687 EFI_OUT_OF_RESOURCES - No buffer could be allocated.
696 EFI_GCD_MAP_ENTRY
*Entry
;
697 EFI_GCD_MAP_ENTRY
*TopEntry
;
698 EFI_GCD_MAP_ENTRY
*BottomEntry
;
699 LIST_ENTRY
*StartLink
;
702 EFI_CPU_ARCH_PROTOCOL
*CpuArch
;
703 UINT64 CpuArchAttributes
;
706 return EFI_INVALID_PARAMETER
;
710 if (Operation
& GCD_MEMORY_SPACE_OPERATION
) {
711 CoreAcquireGcdMemoryLock ();
712 Map
= &mGcdMemorySpaceMap
;
714 if (Operation
& GCD_IO_SPACE_OPERATION
) {
715 CoreAcquireGcdIoLock ();
716 Map
= &mGcdIoSpaceMap
;
720 // Search for the list of descriptors that cover the range BaseAddress to BaseAddress+Length
722 Status
= CoreSearchGcdMapEntry (BaseAddress
, Length
, &StartLink
, &EndLink
, Map
);
723 if (EFI_ERROR (Status
)) {
724 Status
= EFI_UNSUPPORTED
;
730 // Verify that the list of descriptors are unallocated non-existent memory.
733 while (Link
!= EndLink
->ForwardLink
) {
734 Entry
= CR (Link
, EFI_GCD_MAP_ENTRY
, Link
, EFI_GCD_MAP_SIGNATURE
);
739 case GCD_ADD_MEMORY_OPERATION
:
740 if (Entry
->GcdMemoryType
!= EfiGcdMemoryTypeNonExistent
||
741 Entry
->ImageHandle
!= NULL
) {
742 Status
= EFI_ACCESS_DENIED
;
746 case GCD_ADD_IO_OPERATION
:
747 if (Entry
->GcdIoType
!= EfiGcdIoTypeNonExistent
||
748 Entry
->ImageHandle
!= NULL
) {
749 Status
= EFI_ACCESS_DENIED
;
756 case GCD_FREE_MEMORY_OPERATION
:
757 case GCD_FREE_IO_OPERATION
:
758 if (Entry
->ImageHandle
== NULL
) {
759 Status
= EFI_NOT_FOUND
;
766 case GCD_REMOVE_MEMORY_OPERATION
:
767 if (Entry
->GcdMemoryType
== EfiGcdMemoryTypeNonExistent
) {
768 Status
= EFI_NOT_FOUND
;
771 if (Entry
->ImageHandle
!= NULL
) {
772 Status
= EFI_ACCESS_DENIED
;
776 case GCD_REMOVE_IO_OPERATION
:
777 if (Entry
->GcdIoType
== EfiGcdIoTypeNonExistent
) {
778 Status
= EFI_NOT_FOUND
;
781 if (Entry
->ImageHandle
!= NULL
) {
782 Status
= EFI_ACCESS_DENIED
;
787 // Set attribute operations
789 case GCD_SET_ATTRIBUTES_MEMORY_OPERATION
:
790 if (Attributes
& EFI_MEMORY_RUNTIME
) {
791 if ((BaseAddress
& EFI_PAGE_MASK
) != 0 || (Length
& EFI_PAGE_MASK
) != 0) {
792 Status
= EFI_INVALID_PARAMETER
;
797 if ((Entry
->Capabilities
& Attributes
) != Attributes
) {
798 Status
= EFI_UNSUPPORTED
;
803 Link
= Link
->ForwardLink
;
807 // Allocate work space to perform this operation
809 Status
= CoreAllocateGcdMapEntry (&TopEntry
, &BottomEntry
);
810 if (EFI_ERROR (Status
)) {
811 Status
= EFI_OUT_OF_RESOURCES
;
818 if (Operation
== GCD_SET_ATTRIBUTES_MEMORY_OPERATION
) {
820 // Call CPU Arch Protocol to attempt to set attributes on the range
822 CpuArchAttributes
= ConverToCpuArchAttributes (Attributes
);
823 if ( CpuArchAttributes
!= INVALID_CPU_ARCH_ATTRIBUTES
) {
824 Status
= CoreLocateProtocol (&gEfiCpuArchProtocolGuid
, NULL
, (VOID
**)&CpuArch
);
825 if (EFI_ERROR (Status
)) {
826 Status
= EFI_ACCESS_DENIED
;
830 Status
= CpuArch
->SetMemoryAttributes (
836 if (EFI_ERROR (Status
)) {
844 // Convert/Insert the list of descriptors from StartLink to EndLink
847 while (Link
!= EndLink
->ForwardLink
) {
848 Entry
= CR (Link
, EFI_GCD_MAP_ENTRY
, Link
, EFI_GCD_MAP_SIGNATURE
);
849 CoreInsertGcdMapEntry (Link
, Entry
, BaseAddress
, Length
, TopEntry
, BottomEntry
);
854 case GCD_ADD_MEMORY_OPERATION
:
855 Entry
->GcdMemoryType
= GcdMemoryType
;
856 if (GcdMemoryType
== EfiGcdMemoryTypeMemoryMappedIo
) {
857 Entry
->Capabilities
= Capabilities
| EFI_MEMORY_RUNTIME
| EFI_MEMORY_PORT_IO
;
859 Entry
->Capabilities
= Capabilities
| EFI_MEMORY_RUNTIME
;
862 case GCD_ADD_IO_OPERATION
:
863 Entry
->GcdIoType
= GcdIoType
;
868 case GCD_FREE_MEMORY_OPERATION
:
869 case GCD_FREE_IO_OPERATION
:
870 Entry
->ImageHandle
= NULL
;
871 Entry
->DeviceHandle
= NULL
;
876 case GCD_REMOVE_MEMORY_OPERATION
:
877 Entry
->GcdMemoryType
= EfiGcdMemoryTypeNonExistent
;
878 Entry
->Capabilities
= 0;
880 case GCD_REMOVE_IO_OPERATION
:
881 Entry
->GcdIoType
= EfiGcdIoTypeNonExistent
;
884 // Set attribute operations
886 case GCD_SET_ATTRIBUTES_MEMORY_OPERATION
:
887 Entry
->Attributes
= Attributes
;
890 Link
= Link
->ForwardLink
;
896 Status
= CoreCleanupGcdMapEntry (TopEntry
, BottomEntry
, StartLink
, EndLink
, Map
);
899 if (Operation
& GCD_MEMORY_SPACE_OPERATION
) {
900 CoreReleaseGcdMemoryLock ();
902 if (Operation
& GCD_IO_SPACE_OPERATION
) {
903 CoreReleaseGcdIoLock ();
911 CoreAllocateSpaceCheckEntry (
913 IN EFI_GCD_MAP_ENTRY
*Entry
,
914 IN EFI_GCD_MEMORY_TYPE GcdMemoryType
,
915 IN EFI_GCD_IO_TYPE GcdIoType
921 Check whether an entry could be used to allocate space.
925 Operation - Allocate memory or IO
927 Entry - The entry to be tested
929 GcdMemoryType - The desired memory type
931 GcdIoType - The desired IO type
935 EFI_NOT_FOUND - The memory type does not match or there's an image handle on the entry.
937 EFI_UNSUPPORTED - The operation unsupported.
939 EFI_SUCCESS - It's ok for this entry to be used to allocate space.
943 if (Entry
->ImageHandle
!= NULL
) {
944 return EFI_NOT_FOUND
;
947 case GCD_ALLOCATE_MEMORY_OPERATION
:
948 if (Entry
->GcdMemoryType
!= GcdMemoryType
) {
949 return EFI_NOT_FOUND
;
952 case GCD_ALLOCATE_IO_OPERATION
:
953 if (Entry
->GcdIoType
!= GcdIoType
) {
954 return EFI_NOT_FOUND
;
958 return EFI_UNSUPPORTED
;
967 IN EFI_GCD_ALLOCATE_TYPE GcdAllocateType
,
968 IN EFI_GCD_MEMORY_TYPE GcdMemoryType
,
969 IN EFI_GCD_IO_TYPE GcdIoType
,
972 IN OUT EFI_PHYSICAL_ADDRESS
*BaseAddress
,
973 IN EFI_HANDLE ImageHandle
,
974 IN EFI_HANDLE DeviceHandle OPTIONAL
980 Allocate space on specified address and length.
984 Operation - The type of operation (memory or IO)
986 GcdAllocateType - The type of allocate operation
988 GcdMemoryType - The desired memory type
990 GcdIoType - The desired IO type
992 Alignment - Align with 2^Alignment
994 Length - Length to allocate
996 BaseAddress - Base address to allocate
998 ImageHandle - The image handle consume the allocated space.
1000 DeviceHandle - The device handle consume the allocated space.
1004 EFI_INVALID_PARAMETER - Invalid parameter.
1006 EFI_NOT_FOUND - No descriptor for the desired space exists.
1008 EFI_SUCCESS - Space successfully allocated.
1013 EFI_PHYSICAL_ADDRESS AlignmentMask
;
1014 EFI_PHYSICAL_ADDRESS MaxAddress
;
1017 LIST_ENTRY
*SubLink
;
1018 EFI_GCD_MAP_ENTRY
*Entry
;
1019 EFI_GCD_MAP_ENTRY
*TopEntry
;
1020 EFI_GCD_MAP_ENTRY
*BottomEntry
;
1021 LIST_ENTRY
*StartLink
;
1022 LIST_ENTRY
*EndLink
;
1026 // Make sure parameters are valid
1028 if (GcdAllocateType
< 0 || GcdAllocateType
>= EfiGcdMaxAllocateType
) {
1029 return EFI_INVALID_PARAMETER
;
1031 if (GcdMemoryType
< 0 || GcdMemoryType
>= EfiGcdMemoryTypeMaximum
) {
1032 return EFI_INVALID_PARAMETER
;
1034 if (GcdIoType
< 0 || GcdIoType
>= EfiGcdIoTypeMaximum
) {
1035 return EFI_INVALID_PARAMETER
;
1037 if (BaseAddress
== NULL
) {
1038 return EFI_INVALID_PARAMETER
;
1040 if (ImageHandle
== NULL
) {
1041 return EFI_INVALID_PARAMETER
;
1043 if (Alignment
>= 64) {
1044 return EFI_NOT_FOUND
;
1047 return EFI_INVALID_PARAMETER
;
1051 if (Operation
& GCD_MEMORY_SPACE_OPERATION
) {
1052 CoreAcquireGcdMemoryLock ();
1053 Map
= &mGcdMemorySpaceMap
;
1055 if (Operation
& GCD_IO_SPACE_OPERATION
) {
1056 CoreAcquireGcdIoLock ();
1057 Map
= &mGcdIoSpaceMap
;
1064 // Compute alignment bit mask
1066 AlignmentMask
= LShiftU64 (1, Alignment
) - 1;
1068 if (GcdAllocateType
== EfiGcdAllocateAddress
) {
1070 // Verify that the BaseAddress passed in is aligned correctly
1072 if ((*BaseAddress
& AlignmentMask
) != 0) {
1073 Status
= EFI_NOT_FOUND
;
1078 // Search for the list of descriptors that cover the range BaseAddress to BaseAddress+Length
1080 Status
= CoreSearchGcdMapEntry (*BaseAddress
, Length
, &StartLink
, &EndLink
, Map
);
1081 if (EFI_ERROR (Status
)) {
1082 Status
= EFI_NOT_FOUND
;
1087 // Verify that the list of descriptors are unallocated memory matching GcdMemoryType.
1090 while (Link
!= EndLink
->ForwardLink
) {
1091 Entry
= CR (Link
, EFI_GCD_MAP_ENTRY
, Link
, EFI_GCD_MAP_SIGNATURE
);
1092 Link
= Link
->ForwardLink
;
1093 Status
= CoreAllocateSpaceCheckEntry (Operation
, Entry
, GcdMemoryType
, GcdIoType
);
1094 if (EFI_ERROR (Status
)) {
1101 Entry
= CR (Map
->BackLink
, EFI_GCD_MAP_ENTRY
, Link
, EFI_GCD_MAP_SIGNATURE
);
1104 // Compute the maximum address to use in the search algorithm
1106 if (GcdAllocateType
== EfiGcdAllocateMaxAddressSearchBottomUp
||
1107 GcdAllocateType
== EfiGcdAllocateMaxAddressSearchTopDown
) {
1108 MaxAddress
= *BaseAddress
;
1110 MaxAddress
= Entry
->EndAddress
;
1114 // Verify that the list of descriptors are unallocated memory matching GcdMemoryType.
1116 if (GcdAllocateType
== EfiGcdAllocateMaxAddressSearchTopDown
||
1117 GcdAllocateType
== EfiGcdAllocateAnySearchTopDown
) {
1118 Link
= Map
->BackLink
;
1120 Link
= Map
->ForwardLink
;
1122 while (Link
!= Map
) {
1123 Entry
= CR (Link
, EFI_GCD_MAP_ENTRY
, Link
, EFI_GCD_MAP_SIGNATURE
);
1125 if (GcdAllocateType
== EfiGcdAllocateMaxAddressSearchTopDown
||
1126 GcdAllocateType
== EfiGcdAllocateAnySearchTopDown
) {
1127 Link
= Link
->BackLink
;
1129 Link
= Link
->ForwardLink
;
1132 Status
= CoreAllocateSpaceCheckEntry (Operation
, Entry
, GcdMemoryType
, GcdIoType
);
1133 if (EFI_ERROR (Status
)) {
1137 if (GcdAllocateType
== EfiGcdAllocateMaxAddressSearchTopDown
||
1138 GcdAllocateType
== EfiGcdAllocateAnySearchTopDown
) {
1139 if ((Entry
->BaseAddress
+ Length
) > MaxAddress
) {
1142 if (Length
> (Entry
->EndAddress
+ 1)) {
1143 Status
= EFI_NOT_FOUND
;
1146 if (Entry
->EndAddress
> MaxAddress
) {
1147 *BaseAddress
= MaxAddress
;
1149 *BaseAddress
= Entry
->EndAddress
;
1151 *BaseAddress
= (*BaseAddress
+ 1 - Length
) & (~AlignmentMask
);
1153 *BaseAddress
= (Entry
->BaseAddress
+ AlignmentMask
) & (~AlignmentMask
);
1154 if ((*BaseAddress
+ Length
- 1) > MaxAddress
) {
1155 Status
= EFI_NOT_FOUND
;
1161 // Search for the list of descriptors that cover the range BaseAddress to BaseAddress+Length
1163 Status
= CoreSearchGcdMapEntry (*BaseAddress
, Length
, &StartLink
, &EndLink
, Map
);
1164 if (EFI_ERROR (Status
)) {
1165 Status
= EFI_NOT_FOUND
;
1171 // Verify that the list of descriptors are unallocated memory matching GcdMemoryType.
1174 SubLink
= StartLink
;
1175 while (SubLink
!= EndLink
->ForwardLink
) {
1176 Entry
= CR (SubLink
, EFI_GCD_MAP_ENTRY
, Link
, EFI_GCD_MAP_SIGNATURE
);
1177 Status
= CoreAllocateSpaceCheckEntry (Operation
, Entry
, GcdMemoryType
, GcdIoType
);
1178 if (EFI_ERROR (Status
)) {
1183 SubLink
= SubLink
->ForwardLink
;
1191 Status
= EFI_NOT_FOUND
;
1196 // Allocate work space to perform this operation
1198 Status
= CoreAllocateGcdMapEntry (&TopEntry
, &BottomEntry
);
1199 if (EFI_ERROR (Status
)) {
1200 Status
= EFI_OUT_OF_RESOURCES
;
1205 // Convert/Insert the list of descriptors from StartLink to EndLink
1208 while (Link
!= EndLink
->ForwardLink
) {
1209 Entry
= CR (Link
, EFI_GCD_MAP_ENTRY
, Link
, EFI_GCD_MAP_SIGNATURE
);
1210 CoreInsertGcdMapEntry (Link
, Entry
, *BaseAddress
, Length
, TopEntry
, BottomEntry
);
1211 Entry
->ImageHandle
= ImageHandle
;
1212 Entry
->DeviceHandle
= DeviceHandle
;
1213 Link
= Link
->ForwardLink
;
1219 Status
= CoreCleanupGcdMapEntry (TopEntry
, BottomEntry
, StartLink
, EndLink
, Map
);
1222 if (Operation
& GCD_MEMORY_SPACE_OPERATION
) {
1223 CoreReleaseGcdMemoryLock ();
1225 if (Operation
& GCD_IO_SPACE_OPERATION
) {
1226 CoreReleaseGcdIoLock ();
1234 CoreInternalAddMemorySpace (
1235 IN EFI_GCD_MEMORY_TYPE GcdMemoryType
,
1236 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
1238 IN UINT64 Capabilities
1242 Routine Description:
1244 Add a segment of memory to GCD map.
1248 GcdMemoryType - Memory type of the segment.
1250 BaseAddress - Base address of the segment.
1252 Length - Length of the segment.
1254 Capabilities - alterable attributes of the segment.
1258 EFI_INVALID_PARAMETER - Invalid parameters.
1260 EFI_SUCCESS - Successfully add a segment of memory space.
1265 // Make sure parameters are valid
1267 if (GcdMemoryType
<= EfiGcdMemoryTypeNonExistent
|| GcdMemoryType
>= EfiGcdMemoryTypeMaximum
) {
1268 return EFI_INVALID_PARAMETER
;
1271 return CoreConvertSpace (GCD_ADD_MEMORY_OPERATION
, GcdMemoryType
, (EFI_GCD_IO_TYPE
) 0, BaseAddress
, Length
, Capabilities
, 0);
1275 // GCD Core Services
1278 CoreAllocateMemorySpace (
1279 IN EFI_GCD_ALLOCATE_TYPE GcdAllocateType
,
1280 IN EFI_GCD_MEMORY_TYPE GcdMemoryType
,
1283 IN OUT EFI_PHYSICAL_ADDRESS
*BaseAddress
,
1284 IN EFI_HANDLE ImageHandle
,
1285 IN EFI_HANDLE DeviceHandle OPTIONAL
1289 Routine Description:
1291 Allocates nonexistent memory, reserved memory, system memory, or memorymapped
1292 I/O resources from the global coherency domain of the processor.
1296 GcdAllocateType - The type of allocate operation
1298 GcdMemoryType - The desired memory type
1300 Alignment - Align with 2^Alignment
1302 Length - Length to allocate
1304 BaseAddress - Base address to allocate
1306 ImageHandle - The image handle consume the allocated space.
1308 DeviceHandle - The device handle consume the allocated space.
1312 EFI_INVALID_PARAMETER - Invalid parameter.
1314 EFI_NOT_FOUND - No descriptor contains the desired space.
1316 EFI_SUCCESS - Memory space successfully allocated.
1320 return CoreAllocateSpace (
1321 GCD_ALLOCATE_MEMORY_OPERATION
,
1324 (EFI_GCD_IO_TYPE
) 0,
1334 CoreAddMemorySpace (
1335 IN EFI_GCD_MEMORY_TYPE GcdMemoryType
,
1336 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
1338 IN UINT64 Capabilities
1342 Routine Description:
1344 Adds reserved memory, system memory, or memory-mapped I/O resources to the
1345 global coherency domain of the processor.
1349 GcdMemoryType - Memory type of the memory space.
1351 BaseAddress - Base address of the memory space.
1353 Length - Length of the memory space.
1355 Capabilities - alterable attributes of the memory space.
1359 EFI_SUCCESS - Merged this memory space into GCD map.
1364 EFI_PHYSICAL_ADDRESS PageBaseAddress
;
1367 Status
= CoreInternalAddMemorySpace (GcdMemoryType
, BaseAddress
, Length
, Capabilities
);
1369 if (!EFI_ERROR (Status
) && GcdMemoryType
== EfiGcdMemoryTypeSystemMemory
) {
1371 PageBaseAddress
= PageAlignLength (BaseAddress
);
1372 PageLength
= PageAlignLength (BaseAddress
+ Length
- PageBaseAddress
);
1374 Status
= CoreAllocateMemorySpace (
1375 EfiGcdAllocateAddress
,
1380 gDxeCoreImageHandle
,
1384 if (!EFI_ERROR (Status
)) {
1385 CoreAddMemoryDescriptor (
1386 EfiConventionalMemory
,
1388 RShiftU64 (PageLength
, EFI_PAGE_SHIFT
),
1392 for (; PageLength
!= 0; PageLength
-= EFI_PAGE_SIZE
, PageBaseAddress
+= EFI_PAGE_SIZE
) {
1393 Status
= CoreAllocateMemorySpace (
1394 EfiGcdAllocateAddress
,
1399 gDxeCoreImageHandle
,
1403 if (!EFI_ERROR (Status
)) {
1404 CoreAddMemoryDescriptor (
1405 EfiConventionalMemory
,
1418 CoreFreeMemorySpace (
1419 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
1424 Routine Description:
1426 Frees nonexistent memory, reserved memory, system memory, or memory-mapped
1427 I/O resources from the global coherency domain of the processor.
1431 BaseAddress - Base address of the memory space.
1433 Length - Length of the memory space.
1437 EFI_SUCCESS - Space successfully freed.
1441 return CoreConvertSpace (GCD_FREE_MEMORY_OPERATION
, (EFI_GCD_MEMORY_TYPE
) 0, (EFI_GCD_IO_TYPE
) 0, BaseAddress
, Length
, 0, 0);
1445 CoreRemoveMemorySpace (
1446 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
1451 Routine Description:
1453 Removes reserved memory, system memory, or memory-mapped I/O resources from
1454 the global coherency domain of the processor.
1458 BaseAddress - Base address of the memory space.
1460 Length - Length of the memory space.
1464 EFI_SUCCESS - Successfully remove a segment of memory space.
1468 return CoreConvertSpace (GCD_REMOVE_MEMORY_OPERATION
, (EFI_GCD_MEMORY_TYPE
) 0, (EFI_GCD_IO_TYPE
) 0, BaseAddress
, Length
, 0, 0);
1473 BuildMemoryDescriptor (
1474 IN OUT EFI_GCD_MEMORY_SPACE_DESCRIPTOR
*Descriptor
,
1475 IN EFI_GCD_MAP_ENTRY
*Entry
1479 Routine Description:
1481 Build a memory descriptor according to an entry.
1485 Descriptor - The descriptor to be built
1487 Entry - According to this entry
1495 Descriptor
->BaseAddress
= Entry
->BaseAddress
;
1496 Descriptor
->Length
= Entry
->EndAddress
- Entry
->BaseAddress
+ 1;
1497 Descriptor
->Capabilities
= Entry
->Capabilities
;
1498 Descriptor
->Attributes
= Entry
->Attributes
;
1499 Descriptor
->GcdMemoryType
= Entry
->GcdMemoryType
;
1500 Descriptor
->ImageHandle
= Entry
->ImageHandle
;
1501 Descriptor
->DeviceHandle
= Entry
->DeviceHandle
;
1505 CoreGetMemorySpaceDescriptor (
1506 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
1507 OUT EFI_GCD_MEMORY_SPACE_DESCRIPTOR
*Descriptor
1511 Routine Description:
1513 Retrieves the descriptor for a memory region containing a specified address.
1517 BaseAddress - Specified start address
1519 Descriptor - Specified length
1523 EFI_INVALID_PARAMETER - Invalid parameter
1525 EFI_SUCCESS - Successfully get memory space descriptor.
1530 LIST_ENTRY
*StartLink
;
1531 LIST_ENTRY
*EndLink
;
1532 EFI_GCD_MAP_ENTRY
*Entry
;
1535 // Make sure parameters are valid
1537 if (Descriptor
== NULL
) {
1538 return EFI_INVALID_PARAMETER
;
1541 CoreAcquireGcdMemoryLock ();
1544 // Search for the list of descriptors that contain BaseAddress
1546 Status
= CoreSearchGcdMapEntry (BaseAddress
, 1, &StartLink
, &EndLink
, &mGcdMemorySpaceMap
);
1547 if (EFI_ERROR (Status
)) {
1548 Status
= EFI_NOT_FOUND
;
1551 // Copy the contents of the found descriptor into Descriptor
1553 Entry
= CR (StartLink
, EFI_GCD_MAP_ENTRY
, Link
, EFI_GCD_MAP_SIGNATURE
);
1554 BuildMemoryDescriptor (Descriptor
, Entry
);
1557 CoreReleaseGcdMemoryLock ();
1563 CoreSetMemorySpaceAttributes (
1564 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
1566 IN UINT64 Attributes
1570 Routine Description:
1572 Modifies the attributes for a memory region in the global coherency domain of the
1577 BaseAddress - Specified start address
1579 Length - Specified length
1581 Attributes - Specified attributes
1585 EFI_SUCCESS - Successfully set attribute of a segment of memory space.
1589 return CoreConvertSpace (GCD_SET_ATTRIBUTES_MEMORY_OPERATION
, (EFI_GCD_MEMORY_TYPE
) 0, (EFI_GCD_IO_TYPE
) 0, BaseAddress
, Length
, 0, Attributes
);
1593 CoreGetMemorySpaceMap (
1594 OUT UINTN
*NumberOfDescriptors
,
1595 OUT EFI_GCD_MEMORY_SPACE_DESCRIPTOR
**MemorySpaceMap
1599 Routine Description:
1601 Returns a map of the memory resources in the global coherency domain of the
1606 NumberOfDescriptors - Number of descriptors.
1608 MemorySpaceMap - Descriptor array
1612 EFI_INVALID_PARAMETER - Invalid parameter
1614 EFI_OUT_OF_RESOURCES - No enough buffer to allocate
1616 EFI_SUCCESS - Successfully get memory space map.
1622 EFI_GCD_MAP_ENTRY
*Entry
;
1623 EFI_GCD_MEMORY_SPACE_DESCRIPTOR
*Descriptor
;
1626 // Make sure parameters are valid
1628 if (NumberOfDescriptors
== NULL
) {
1629 return EFI_INVALID_PARAMETER
;
1631 if (MemorySpaceMap
== NULL
) {
1632 return EFI_INVALID_PARAMETER
;
1635 CoreAcquireGcdMemoryLock ();
1638 // Count the number of descriptors
1640 *NumberOfDescriptors
= CoreCountGcdMapEntry (&mGcdMemorySpaceMap
);
1643 // Allocate the MemorySpaceMap
1645 *MemorySpaceMap
= CoreAllocateBootServicesPool (*NumberOfDescriptors
* sizeof (EFI_GCD_MEMORY_SPACE_DESCRIPTOR
));
1646 if (*MemorySpaceMap
== NULL
) {
1647 Status
= EFI_OUT_OF_RESOURCES
;
1652 // Fill in the MemorySpaceMap
1654 Descriptor
= *MemorySpaceMap
;
1655 Link
= mGcdMemorySpaceMap
.ForwardLink
;
1656 while (Link
!= &mGcdMemorySpaceMap
) {
1657 Entry
= CR (Link
, EFI_GCD_MAP_ENTRY
, Link
, EFI_GCD_MAP_SIGNATURE
);
1658 BuildMemoryDescriptor (Descriptor
, Entry
);
1660 Link
= Link
->ForwardLink
;
1662 Status
= EFI_SUCCESS
;
1665 CoreReleaseGcdMemoryLock ();
1671 IN EFI_GCD_IO_TYPE GcdIoType
,
1672 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
1677 Routine Description:
1679 Adds reserved I/O or I/O resources to the global coherency domain of the processor.
1683 GcdIoType - IO type of the segment.
1685 BaseAddress - Base address of the segment.
1687 Length - Length of the segment.
1691 EFI_SUCCESS - Merged this segment into GCD map.
1692 EFI_INVALID_PARAMETER - Parameter not valid
1697 // Make sure parameters are valid
1699 if (GcdIoType
<= EfiGcdIoTypeNonExistent
|| GcdIoType
>= EfiGcdIoTypeMaximum
) {
1700 return EFI_INVALID_PARAMETER
;
1702 return CoreConvertSpace (GCD_ADD_IO_OPERATION
, (EFI_GCD_MEMORY_TYPE
) 0, GcdIoType
, BaseAddress
, Length
, 0, 0);
1706 CoreAllocateIoSpace (
1707 IN EFI_GCD_ALLOCATE_TYPE GcdAllocateType
,
1708 IN EFI_GCD_IO_TYPE GcdIoType
,
1711 IN OUT EFI_PHYSICAL_ADDRESS
*BaseAddress
,
1712 IN EFI_HANDLE ImageHandle
,
1713 IN EFI_HANDLE DeviceHandle OPTIONAL
1717 Routine Description:
1719 Allocates nonexistent I/O, reserved I/O, or I/O resources from the global coherency
1720 domain of the processor.
1724 GcdAllocateType - The type of allocate operation
1726 GcdIoType - The desired IO type
1728 Alignment - Align with 2^Alignment
1730 Length - Length to allocate
1732 BaseAddress - Base address to allocate
1734 ImageHandle - The image handle consume the allocated space.
1736 DeviceHandle - The device handle consume the allocated space.
1740 EFI_INVALID_PARAMETER - Invalid parameter.
1742 EFI_NOT_FOUND - No descriptor contains the desired space.
1744 EFI_SUCCESS - IO space successfully allocated.
1748 return CoreAllocateSpace (
1749 GCD_ALLOCATE_IO_OPERATION
,
1751 (EFI_GCD_MEMORY_TYPE
) 0,
1763 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
1768 Routine Description:
1770 Frees nonexistent I/O, reserved I/O, or I/O resources from the global coherency
1771 domain of the processor.
1775 BaseAddress - Base address of the segment.
1777 Length - Length of the segment.
1781 EFI_SUCCESS - Space successfully freed.
1785 return CoreConvertSpace (GCD_FREE_IO_OPERATION
, (EFI_GCD_MEMORY_TYPE
) 0, (EFI_GCD_IO_TYPE
) 0, BaseAddress
, Length
, 0, 0);
1790 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
1795 Routine Description:
1797 Removes reserved I/O or I/O resources from the global coherency domain of the
1802 BaseAddress - Base address of the segment.
1804 Length - Length of the segment.
1808 EFI_SUCCESS - Successfully removed a segment of IO space.
1812 return CoreConvertSpace (GCD_REMOVE_IO_OPERATION
, (EFI_GCD_MEMORY_TYPE
) 0, (EFI_GCD_IO_TYPE
) 0, BaseAddress
, Length
, 0, 0);
1818 IN EFI_GCD_IO_SPACE_DESCRIPTOR
*Descriptor
,
1819 IN EFI_GCD_MAP_ENTRY
*Entry
1823 Routine Description:
1825 Build a IO descriptor according to an entry.
1829 Descriptor - The descriptor to be built
1831 Entry - According to this entry
1839 Descriptor
->BaseAddress
= Entry
->BaseAddress
;
1840 Descriptor
->Length
= Entry
->EndAddress
- Entry
->BaseAddress
+ 1;
1841 Descriptor
->GcdIoType
= Entry
->GcdIoType
;
1842 Descriptor
->ImageHandle
= Entry
->ImageHandle
;
1843 Descriptor
->DeviceHandle
= Entry
->DeviceHandle
;
1847 CoreGetIoSpaceDescriptor (
1848 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
1849 OUT EFI_GCD_IO_SPACE_DESCRIPTOR
*Descriptor
1853 Routine Description:
1855 Retrieves the descriptor for an I/O region containing a specified address.
1859 BaseAddress - Specified start address
1861 Descriptor - Specified length
1865 EFI_INVALID_PARAMETER - Descriptor is NULL.
1867 EFI_SUCCESS - Successfully get the IO space descriptor.
1872 LIST_ENTRY
*StartLink
;
1873 LIST_ENTRY
*EndLink
;
1874 EFI_GCD_MAP_ENTRY
*Entry
;
1877 // Make sure parameters are valid
1879 if (Descriptor
== NULL
) {
1880 return EFI_INVALID_PARAMETER
;
1883 CoreAcquireGcdIoLock ();
1886 // Search for the list of descriptors that contain BaseAddress
1888 Status
= CoreSearchGcdMapEntry (BaseAddress
, 1, &StartLink
, &EndLink
, &mGcdIoSpaceMap
);
1889 if (EFI_ERROR (Status
)) {
1890 Status
= EFI_NOT_FOUND
;
1893 // Copy the contents of the found descriptor into Descriptor
1895 Entry
= CR (StartLink
, EFI_GCD_MAP_ENTRY
, Link
, EFI_GCD_MAP_SIGNATURE
);
1896 BuildIoDescriptor (Descriptor
, Entry
);
1899 CoreReleaseGcdIoLock ();
1906 OUT UINTN
*NumberOfDescriptors
,
1907 OUT EFI_GCD_IO_SPACE_DESCRIPTOR
**IoSpaceMap
1911 Routine Description:
1913 Returns a map of the I/O resources in the global coherency domain of the processor.
1917 NumberOfDescriptors - Number of descriptors.
1919 IoSpaceMap - Descriptor array
1923 EFI_INVALID_PARAMETER - Invalid parameter
1925 EFI_OUT_OF_RESOURCES - No enough buffer to allocate
1927 EFI_SUCCESS - Successfully get IO space map.
1933 EFI_GCD_MAP_ENTRY
*Entry
;
1934 EFI_GCD_IO_SPACE_DESCRIPTOR
*Descriptor
;
1937 // Make sure parameters are valid
1939 if (NumberOfDescriptors
== NULL
) {
1940 return EFI_INVALID_PARAMETER
;
1942 if (IoSpaceMap
== NULL
) {
1943 return EFI_INVALID_PARAMETER
;
1946 CoreAcquireGcdIoLock ();
1949 // Count the number of descriptors
1951 *NumberOfDescriptors
= CoreCountGcdMapEntry (&mGcdIoSpaceMap
);
1954 // Allocate the IoSpaceMap
1956 *IoSpaceMap
= CoreAllocateBootServicesPool (*NumberOfDescriptors
* sizeof (EFI_GCD_IO_SPACE_DESCRIPTOR
));
1957 if (*IoSpaceMap
== NULL
) {
1958 Status
= EFI_OUT_OF_RESOURCES
;
1963 // Fill in the IoSpaceMap
1965 Descriptor
= *IoSpaceMap
;
1966 Link
= mGcdIoSpaceMap
.ForwardLink
;
1967 while (Link
!= &mGcdIoSpaceMap
) {
1968 Entry
= CR (Link
, EFI_GCD_MAP_ENTRY
, Link
, EFI_GCD_MAP_SIGNATURE
);
1969 BuildIoDescriptor (Descriptor
, Entry
);
1971 Link
= Link
->ForwardLink
;
1973 Status
= EFI_SUCCESS
;
1976 CoreReleaseGcdIoLock ();
1982 CoreConvertResourceDescriptorHobAttributesToCapabilities (
1983 EFI_GCD_MEMORY_TYPE GcdMemoryType
,
1988 Routine Description:
1990 Converts a Resource Descriptor HOB attributes mask to an EFI Memory Descriptor
1995 GcdMemoryType - Type of resource in the GCD memory map.
1996 Attributes - The attribute mask in the Resource Descriptor HOB.
2000 The capabilities mask for an EFI Memory Descriptor.
2004 UINT64 Capabilities
;
2005 GCD_ATTRIBUTE_CONVERSION_ENTRY
*Conversion
;
2008 // Convert the Resource HOB Attributes to an EFI Memory Capabilities mask
2010 for (Capabilities
= 0, Conversion
= mAttributeConversionTable
; Conversion
->Attribute
!= 0; Conversion
++) {
2011 if (Conversion
->Memory
|| (GcdMemoryType
!= EfiGcdMemoryTypeSystemMemory
)) {
2012 if (Attributes
& Conversion
->Attribute
) {
2013 Capabilities
|= Conversion
->Capability
;
2018 return Capabilities
;
2022 CoreInitializeMemoryServices (
2024 OUT EFI_PHYSICAL_ADDRESS
*MemoryBaseAddress
,
2025 OUT UINT64
*MemoryLength
2029 Routine Description:
2031 External function. Initializes the GCD and memory services based on the memory
2032 descriptor HOBs. This function is responsible for priming the GCD map and the
2033 memory map, so memory allocations and resource allocations can be made. The first
2034 part of this function can not depend on any memory services until at least one
2035 memory descriptor is provided to the memory services. Then the memory services
2036 can be used to intialize the GCD map.
2040 HobStart - The start address of the HOB.
2041 MemoryBaseAddress - Start address of memory region found to init DXE core.
2042 MemoryLength - Length of memory region found to init DXE core.
2046 EFI_SUCCESS - Memory services successfully initialized.
2050 EFI_PEI_HOB_POINTERS Hob
;
2051 EFI_MEMORY_TYPE_INFORMATION
*EfiMemoryTypeInformation
;
2054 EFI_HOB_HANDOFF_INFO_TABLE
*PhitHob
;
2055 EFI_HOB_RESOURCE_DESCRIPTOR
*ResourceHob
;
2056 EFI_HOB_RESOURCE_DESCRIPTOR
*PhitResourceHob
;
2057 EFI_PHYSICAL_ADDRESS BaseAddress
;
2060 UINT64 Capabilities
;
2061 EFI_PHYSICAL_ADDRESS MaxMemoryBaseAddress
;
2062 UINT64 MaxMemoryLength
;
2063 UINT64 MaxMemoryAttributes
;
2064 EFI_PHYSICAL_ADDRESS MaxAddress
;
2065 EFI_PHYSICAL_ADDRESS HighAddress
;
2066 EFI_HOB_RESOURCE_DESCRIPTOR
*MaxResourceHob
;
2067 EFI_HOB_GUID_TYPE
*GuidHob
;
2070 // Point at the first HOB. This must be the PHIT HOB.
2072 Hob
.Raw
= *HobStart
;
2073 ASSERT (GET_HOB_TYPE (Hob
) == EFI_HOB_TYPE_HANDOFF
);
2076 // Initialize the spin locks and maps in the memory services.
2077 // Also fill in the memory services into the EFI Boot Services Table
2079 CoreInitializePool ();
2082 // Initialize Local Variables
2084 PhitResourceHob
= NULL
;
2085 MaxResourceHob
= NULL
;
2090 MaxMemoryBaseAddress
= 0;
2091 MaxMemoryLength
= 0;
2092 MaxMemoryAttributes
= 0;
2095 // Cache the PHIT HOB for later use
2097 PhitHob
= Hob
.HandoffInformationTable
;
2100 // See if a Memory Type Information HOB is available
2102 GuidHob
= GetFirstGuidHob (&gEfiMemoryTypeInformationGuid
);
2103 if (GuidHob
!= NULL
) {
2104 EfiMemoryTypeInformation
= GET_GUID_HOB_DATA (GuidHob
);
2105 DataSize
= GET_GUID_HOB_DATA_SIZE (GuidHob
);
2106 if (EfiMemoryTypeInformation
!= NULL
&& DataSize
> 0 && DataSize
<= (EfiMaxMemoryType
+ 1) * sizeof (EFI_MEMORY_TYPE_INFORMATION
)) {
2107 CopyMem (&gMemoryTypeInformation
, EfiMemoryTypeInformation
, DataSize
);
2112 // Find the Resource Descriptor HOB that contains range FreeMemoryBaseAddress..FreeMemoryLength
2116 for (Hob
.Raw
= *HobStart
; !END_OF_HOB_LIST(Hob
); Hob
.Raw
= GET_NEXT_HOB(Hob
)) {
2118 if (GET_HOB_TYPE (Hob
) == EFI_HOB_TYPE_RESOURCE_DESCRIPTOR
) {
2120 ResourceHob
= Hob
.ResourceDescriptor
;
2122 if (ResourceHob
->ResourceType
== EFI_RESOURCE_SYSTEM_MEMORY
&&
2123 (ResourceHob
->ResourceAttribute
& MEMORY_ATTRIBUTE_MASK
) == TESTED_MEMORY_ATTRIBUTES
) {
2125 if (PhitHob
->EfiFreeMemoryBottom
>= ResourceHob
->PhysicalStart
&&
2126 PhitHob
->EfiFreeMemoryTop
<= (ResourceHob
->PhysicalStart
+ ResourceHob
->ResourceLength
) ) {
2129 // Cache the resource descriptor HOB for the memory region described by the PHIT HOB
2131 PhitResourceHob
= ResourceHob
;
2134 Attributes
= PhitResourceHob
->ResourceAttribute
;
2135 BaseAddress
= PageAlignAddress (PhitHob
->EfiMemoryTop
);
2136 Length
= PageAlignLength (ResourceHob
->PhysicalStart
+ ResourceHob
->ResourceLength
- BaseAddress
);
2137 if (Length
< MINIMUM_INITIAL_MEMORY_SIZE
) {
2138 BaseAddress
= PageAlignAddress (PhitHob
->EfiFreeMemoryBottom
);
2139 Length
= PageAlignLength (PhitHob
->EfiFreeMemoryTop
- BaseAddress
);
2140 if (Length
< MINIMUM_INITIAL_MEMORY_SIZE
) {
2141 BaseAddress
= PageAlignAddress (ResourceHob
->PhysicalStart
);
2142 Length
= PageAlignLength ((UINT64
)((UINTN
)*HobStart
- BaseAddress
));
2152 // Assert if a resource descriptor HOB for the memory region described by the PHIT was not found
2157 // Search all the resource descriptor HOBs from the highest possible addresses down for a memory
2158 // region that is big enough to initialize the DXE core. Always skip the PHIT Resource HOB.
2159 // The max address must be within the physically addressible range for the processor.
2161 MaxMemoryLength
= 0;
2162 MaxAddress
= EFI_MAX_ADDRESS
;
2167 // Search for a tested memory region that is below MaxAddress
2169 for (Hob
.Raw
= *HobStart
; !END_OF_HOB_LIST(Hob
); Hob
.Raw
= GET_NEXT_HOB(Hob
)) {
2172 // See if this is a resource descriptor HOB that does not contain the PHIT.
2174 if (Hob
.ResourceDescriptor
!= PhitResourceHob
&& GET_HOB_TYPE (Hob
) == EFI_HOB_TYPE_RESOURCE_DESCRIPTOR
) {
2176 ResourceHob
= Hob
.ResourceDescriptor
;
2178 // See if this resource descrior HOB describes tested system memory below MaxAddress
2180 if (ResourceHob
->ResourceType
== EFI_RESOURCE_SYSTEM_MEMORY
&&
2181 (ResourceHob
->ResourceAttribute
& MEMORY_ATTRIBUTE_MASK
) == TESTED_MEMORY_ATTRIBUTES
&&
2182 ResourceHob
->PhysicalStart
+ ResourceHob
->ResourceLength
<= MaxAddress
) {
2185 // See if this is the highest tested system memory region below MaxAddress
2187 if (ResourceHob
->PhysicalStart
> HighAddress
) {
2189 MaxResourceHob
= ResourceHob
;
2190 HighAddress
= MaxResourceHob
->PhysicalStart
;
2198 // Compute the size of the tested memory region below MaxAddrees
2200 MaxMemoryBaseAddress
= PageAlignAddress (MaxResourceHob
->PhysicalStart
);
2201 MaxMemoryLength
= PageAlignLength (MaxResourceHob
->PhysicalStart
+ MaxResourceHob
->ResourceLength
- MaxMemoryBaseAddress
);
2202 MaxMemoryAttributes
= MaxResourceHob
->ResourceAttribute
;
2204 MaxAddress
= ResourceHob
->PhysicalStart
;
2205 } while (Found
&& MaxMemoryLength
< MINIMUM_INITIAL_MEMORY_SIZE
);
2210 if ((Length
< MINIMUM_INITIAL_MEMORY_SIZE
) ||
2211 (MaxMemoryBaseAddress
> BaseAddress
&& MaxMemoryLength
>= MINIMUM_INITIAL_MEMORY_SIZE
) ) {
2212 BaseAddress
= MaxMemoryBaseAddress
;
2213 Length
= MaxMemoryLength
;
2214 Attributes
= MaxMemoryAttributes
;
2218 // If no memory regions are found that are big enough to initialize the DXE core, then ASSERT().
2220 ASSERT (Length
>= MINIMUM_INITIAL_MEMORY_SIZE
);
2223 // Convert the Resource HOB Attributes to an EFI Memory Capabilities mask
2225 Capabilities
= CoreConvertResourceDescriptorHobAttributesToCapabilities (EfiGcdMemoryTypeSystemMemory
, Attributes
);
2228 // Declare the very first memory region, so the EFI Memory Services are available.
2230 CoreAddMemoryDescriptor (
2231 EfiConventionalMemory
,
2233 RShiftU64 (Length
, EFI_PAGE_SHIFT
),
2237 *MemoryBaseAddress
= BaseAddress
;
2238 *MemoryLength
= Length
;
2244 CoreInitializeGcdServices (
2246 IN EFI_PHYSICAL_ADDRESS MemoryBaseAddress
,
2247 IN UINT64 MemoryLength
2251 Routine Description:
2253 External function. Initializes the GCD and memory services based on the memory
2254 descriptor HOBs. This function is responsible for priming the GCD map and the
2255 memory map, so memory allocations and resource allocations can be made. The first
2256 part of this function can not depend on any memory services until at least one
2257 memory descriptor is provided to the memory services. Then the memory services
2258 can be used to intialize the GCD map.
2262 HobStart - The start address of the HOB
2264 MemoryBaseAddress - Start address of memory region found to init DXE core.
2266 MemoryLength - Length of memory region found to init DXE core.
2271 EFI_SUCCESS - GCD services successfully initialized.
2275 EFI_PEI_HOB_POINTERS Hob
;
2277 EFI_HOB_HANDOFF_INFO_TABLE
*PhitHob
;
2278 UINT8 SizeOfMemorySpace
;
2279 UINT8 SizeOfIoSpace
;
2280 EFI_HOB_RESOURCE_DESCRIPTOR
*ResourceHob
;
2281 EFI_PHYSICAL_ADDRESS BaseAddress
;
2284 EFI_GCD_MAP_ENTRY
*Entry
;
2285 EFI_GCD_MEMORY_TYPE GcdMemoryType
;
2286 EFI_GCD_IO_TYPE GcdIoType
;
2287 EFI_GCD_MEMORY_SPACE_DESCRIPTOR Descriptor
;
2288 EFI_HOB_MEMORY_ALLOCATION
*MemoryHob
;
2289 EFI_HOB_FIRMWARE_VOLUME
*FirmwareVolumeHob
;
2290 UINTN NumberOfDescriptors
;
2291 EFI_GCD_MEMORY_SPACE_DESCRIPTOR
*MemorySpaceMap
;
2293 UINT64 Capabilities
;
2294 EFI_HOB_CPU
* CpuHob
;
2296 // Cache the PHIT HOB for later use
2298 PhitHob
= (EFI_HOB_HANDOFF_INFO_TABLE
*)(*HobStart
);
2301 // Get the number of address lines in the I/O and Memory space for the CPU
2303 CpuHob
= GetFirstHob (EFI_HOB_TYPE_CPU
);
2304 ASSERT (CpuHob
!= NULL
);
2305 SizeOfMemorySpace
= CpuHob
->SizeOfMemorySpace
;
2306 SizeOfIoSpace
= CpuHob
->SizeOfIoSpace
;
2309 // Initialize the GCD Memory Space Map
2311 Entry
= CoreAllocateCopyPool (sizeof (EFI_GCD_MAP_ENTRY
), &mGcdMemorySpaceMapEntryTemplate
);
2312 ASSERT (Entry
!= NULL
);
2314 Entry
->EndAddress
= LShiftU64 (1, SizeOfMemorySpace
) - 1;
2316 InsertHeadList (&mGcdMemorySpaceMap
, &Entry
->Link
);
2319 // Initialize the GCD I/O Space Map
2321 Entry
= CoreAllocateCopyPool (sizeof (EFI_GCD_MAP_ENTRY
), &mGcdIoSpaceMapEntryTemplate
);
2322 ASSERT (Entry
!= NULL
);
2324 Entry
->EndAddress
= LShiftU64 (1, SizeOfIoSpace
) - 1;
2326 InsertHeadList (&mGcdIoSpaceMap
, &Entry
->Link
);
2329 // Walk the HOB list and add all resource descriptors to the GCD
2331 for (Hob
.Raw
= *HobStart
; !END_OF_HOB_LIST(Hob
); Hob
.Raw
= GET_NEXT_HOB(Hob
)) {
2333 GcdMemoryType
= EfiGcdMemoryTypeNonExistent
;
2334 GcdIoType
= EfiGcdIoTypeNonExistent
;
2336 if (GET_HOB_TYPE (Hob
) == EFI_HOB_TYPE_RESOURCE_DESCRIPTOR
) {
2338 ResourceHob
= Hob
.ResourceDescriptor
;
2340 switch (ResourceHob
->ResourceType
) {
2341 case EFI_RESOURCE_SYSTEM_MEMORY
:
2342 if ((ResourceHob
->ResourceAttribute
& MEMORY_ATTRIBUTE_MASK
) == TESTED_MEMORY_ATTRIBUTES
) {
2343 GcdMemoryType
= EfiGcdMemoryTypeSystemMemory
;
2345 if ((ResourceHob
->ResourceAttribute
& MEMORY_ATTRIBUTE_MASK
) == INITIALIZED_MEMORY_ATTRIBUTES
) {
2346 GcdMemoryType
= EfiGcdMemoryTypeReserved
;
2348 if ((ResourceHob
->ResourceAttribute
& MEMORY_ATTRIBUTE_MASK
) == PRESENT_MEMORY_ATTRIBUTES
) {
2349 GcdMemoryType
= EfiGcdMemoryTypeReserved
;
2352 case EFI_RESOURCE_MEMORY_MAPPED_IO
:
2353 case EFI_RESOURCE_FIRMWARE_DEVICE
:
2354 GcdMemoryType
= EfiGcdMemoryTypeMemoryMappedIo
;
2356 case EFI_RESOURCE_MEMORY_MAPPED_IO_PORT
:
2357 case EFI_RESOURCE_MEMORY_RESERVED
:
2358 GcdMemoryType
= EfiGcdMemoryTypeReserved
;
2360 case EFI_RESOURCE_IO
:
2361 GcdIoType
= EfiGcdIoTypeIo
;
2363 case EFI_RESOURCE_IO_RESERVED
:
2364 GcdIoType
= EfiGcdIoTypeReserved
;
2368 if (GcdMemoryType
!= EfiGcdMemoryTypeNonExistent
) {
2371 // Convert the Resource HOB Attributes to an EFI Memory Capabilities mask
2373 Capabilities
= CoreConvertResourceDescriptorHobAttributesToCapabilities (
2375 ResourceHob
->ResourceAttribute
2378 Status
= CoreInternalAddMemorySpace (
2380 ResourceHob
->PhysicalStart
,
2381 ResourceHob
->ResourceLength
,
2386 if (GcdIoType
!= EfiGcdIoTypeNonExistent
) {
2387 Status
= CoreAddIoSpace (
2389 ResourceHob
->PhysicalStart
,
2390 ResourceHob
->ResourceLength
2397 // Allocate first memory region from the GCD by the DXE core
2399 Status
= CoreAllocateMemorySpace (
2400 EfiGcdAllocateAddress
,
2401 EfiGcdMemoryTypeSystemMemory
,
2405 gDxeCoreImageHandle
,
2410 // Walk the HOB list and allocate all memory space that is consumed by memory allocation HOBs,
2411 // and Firmware Volume HOBs. Also update the EFI Memory Map with the memory allocation HOBs.
2413 for (Hob
.Raw
= *HobStart
; !END_OF_HOB_LIST(Hob
); Hob
.Raw
= GET_NEXT_HOB(Hob
)) {
2414 if (GET_HOB_TYPE (Hob
) == EFI_HOB_TYPE_MEMORY_ALLOCATION
) {
2415 MemoryHob
= Hob
.MemoryAllocation
;
2416 BaseAddress
= MemoryHob
->AllocDescriptor
.MemoryBaseAddress
;
2417 Status
= CoreAllocateMemorySpace (
2418 EfiGcdAllocateAddress
,
2419 EfiGcdMemoryTypeSystemMemory
,
2421 MemoryHob
->AllocDescriptor
.MemoryLength
,
2423 gDxeCoreImageHandle
,
2426 if (!EFI_ERROR (Status
)) {
2427 Status
= CoreGetMemorySpaceDescriptor (MemoryHob
->AllocDescriptor
.MemoryBaseAddress
, &Descriptor
);
2428 if (!EFI_ERROR (Status
)) {
2429 CoreAddMemoryDescriptor (
2430 MemoryHob
->AllocDescriptor
.MemoryType
,
2431 MemoryHob
->AllocDescriptor
.MemoryBaseAddress
,
2432 RShiftU64 (MemoryHob
->AllocDescriptor
.MemoryLength
, EFI_PAGE_SHIFT
),
2433 Descriptor
.Capabilities
& (~EFI_MEMORY_RUNTIME
)
2439 if (GET_HOB_TYPE (Hob
) == EFI_HOB_TYPE_FV
) {
2440 FirmwareVolumeHob
= Hob
.FirmwareVolume
;
2441 BaseAddress
= FirmwareVolumeHob
->BaseAddress
;
2442 Status
= CoreAllocateMemorySpace (
2443 EfiGcdAllocateAddress
,
2444 EfiGcdMemoryTypeMemoryMappedIo
,
2446 FirmwareVolumeHob
->Length
,
2448 gDxeCoreImageHandle
,
2455 // Relocate HOB List to an allocated pool buffer.
2457 NewHobList
= CoreAllocateCopyPool (
2458 (UINTN
)PhitHob
->EfiFreeMemoryBottom
- (UINTN
)(*HobStart
),
2461 ASSERT (NewHobList
!= NULL
);
2463 *HobStart
= NewHobList
;
2466 // Add and allocate the remaining unallocated system memory to the memory services.
2468 Status
= CoreGetMemorySpaceMap (&NumberOfDescriptors
, &MemorySpaceMap
);
2469 for (Index
= 0; Index
< NumberOfDescriptors
; Index
++) {
2470 if (MemorySpaceMap
[Index
].GcdMemoryType
== EfiGcdMemoryTypeSystemMemory
) {
2471 if (MemorySpaceMap
[Index
].ImageHandle
== NULL
) {
2472 BaseAddress
= PageAlignAddress (MemorySpaceMap
[Index
].BaseAddress
);
2473 Length
= PageAlignLength (MemorySpaceMap
[Index
].BaseAddress
+ MemorySpaceMap
[Index
].Length
- BaseAddress
);
2474 CoreAddMemoryDescriptor (
2475 EfiConventionalMemory
,
2477 RShiftU64 (Length
, EFI_PAGE_SHIFT
),
2478 MemorySpaceMap
[Index
].Capabilities
& (~EFI_MEMORY_RUNTIME
)
2480 Status
= CoreAllocateMemorySpace (
2481 EfiGcdAllocateAddress
,
2482 EfiGcdMemoryTypeSystemMemory
,
2486 gDxeCoreImageHandle
,
2492 CoreFreePool (MemorySpaceMap
);