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
,
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
196 Aligns a value to the specified boundary.
200 Value - 64 bit value to align
201 Alignment - Log base 2 of the boundary to align Value to
202 RoundUp - TRUE if Value is to be rounded up to the nearest aligned boundary.
203 FALSE is Value is to be rounded down to the nearest aligned boundary.
207 A 64 bit value is the aligned to the value nearest Value with an alignment by Alignment.
211 UINT64 AlignmentMask
;
213 AlignmentMask
= LShiftU64 (1, Alignment
) - 1;
215 Value
+= AlignmentMask
;
217 return Value
& (~AlignmentMask
);
228 Aligns address to the page boundary.
232 Value - 64 bit address to align
236 A 64 bit value is the aligned to the value nearest Value with an alignment by Alignment.
240 return AlignValue (Value
, EFI_PAGE_SHIFT
, TRUE
);
251 Aligns length to the page boundary.
255 Value - 64 bit length to align
259 A 64 bit value is the aligned to the value nearest Value with an alignment by Alignment.
263 return AlignValue (Value
, EFI_PAGE_SHIFT
, FALSE
);
267 // GCD Memory Space Worker Functions
270 CoreAllocateGcdMapEntry (
271 IN OUT EFI_GCD_MAP_ENTRY
**TopEntry
,
272 IN OUT EFI_GCD_MAP_ENTRY
**BottomEntry
278 Allocate pool for two entries.
282 TopEntry - An entry of GCD map
283 BottomEntry - An entry of GCD map
287 EFI_OUT_OF_RESOURCES - No enough buffer to be allocated.
288 EFI_SUCCESS - Both entries successfully allocated.
292 *TopEntry
= CoreAllocateZeroBootServicesPool (sizeof (EFI_GCD_MAP_ENTRY
));
293 if (*TopEntry
== NULL
) {
294 return EFI_OUT_OF_RESOURCES
;
297 *BottomEntry
= CoreAllocateZeroBootServicesPool (sizeof (EFI_GCD_MAP_ENTRY
));
298 if (*BottomEntry
== NULL
) {
299 CoreFreePool (*TopEntry
);
300 return EFI_OUT_OF_RESOURCES
;
307 CoreInsertGcdMapEntry (
309 IN EFI_GCD_MAP_ENTRY
*Entry
,
310 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
312 IN EFI_GCD_MAP_ENTRY
*TopEntry
,
313 IN EFI_GCD_MAP_ENTRY
*BottomEntry
319 Internal function. Inserts a new descriptor into a sorted list
323 Link - The linked list to insert the range BaseAddress and Length into
325 Entry - A pointer to the entry that is inserted
327 BaseAddress - The base address of the new range
329 Length - The length of the new range in bytes
331 TopEntry - Top pad entry to insert if needed.
333 BottomEntry - Bottom pad entry to insert if needed.
337 EFI_SUCCESS - The new range was inserted into the linked list
341 ASSERT (Length
!= 0);
342 ASSERT (TopEntry
->Signature
== 0);
343 ASSERT (BottomEntry
->Signature
== 0);
345 if (BaseAddress
> Entry
->BaseAddress
) {
346 CopyMem (BottomEntry
, Entry
, sizeof (EFI_GCD_MAP_ENTRY
));
347 Entry
->BaseAddress
= BaseAddress
;
348 BottomEntry
->EndAddress
= BaseAddress
- 1;
349 InsertTailList (Link
, &BottomEntry
->Link
);
352 if ((BaseAddress
+ Length
- 1) < Entry
->EndAddress
) {
353 CopyMem (TopEntry
, Entry
, sizeof (EFI_GCD_MAP_ENTRY
));
354 TopEntry
->BaseAddress
= BaseAddress
+ Length
;
355 Entry
->EndAddress
= BaseAddress
+ Length
- 1;
356 InsertHeadList (Link
, &TopEntry
->Link
);
363 CoreMergeGcdMapEntry (
372 Merge the Gcd region specified by Link and its adjacent entry
376 Link - Specify the entry to be merged (with its adjacent entry).
378 Forward - Direction (forward or backward).
384 EFI_SUCCESS - Successfully returned.
386 EFI_UNSUPPORTED - These adjacent regions could not merge.
390 LIST_ENTRY
*AdjacentLink
;
391 EFI_GCD_MAP_ENTRY
*Entry
;
392 EFI_GCD_MAP_ENTRY
*AdjacentEntry
;
395 // Get adjacent entry
398 AdjacentLink
= Link
->ForwardLink
;
400 AdjacentLink
= Link
->BackLink
;
404 // If AdjacentLink is the head of the list, then no merge can be performed
406 if (AdjacentLink
== Map
) {
410 Entry
= CR (Link
, EFI_GCD_MAP_ENTRY
, Link
, EFI_GCD_MAP_SIGNATURE
);
411 AdjacentEntry
= CR (AdjacentLink
, EFI_GCD_MAP_ENTRY
, Link
, EFI_GCD_MAP_SIGNATURE
);
413 if (Entry
->Capabilities
!= AdjacentEntry
->Capabilities
) {
414 return EFI_UNSUPPORTED
;
416 if (Entry
->Attributes
!= AdjacentEntry
->Attributes
) {
417 return EFI_UNSUPPORTED
;
419 if (Entry
->GcdMemoryType
!= AdjacentEntry
->GcdMemoryType
) {
420 return EFI_UNSUPPORTED
;
422 if (Entry
->GcdIoType
!= AdjacentEntry
->GcdIoType
) {
423 return EFI_UNSUPPORTED
;
425 if (Entry
->ImageHandle
!= AdjacentEntry
->ImageHandle
) {
426 return EFI_UNSUPPORTED
;
428 if (Entry
->DeviceHandle
!= AdjacentEntry
->DeviceHandle
) {
429 return EFI_UNSUPPORTED
;
433 Entry
->EndAddress
= AdjacentEntry
->EndAddress
;
435 Entry
->BaseAddress
= AdjacentEntry
->BaseAddress
;
437 RemoveEntryList (AdjacentLink
);
438 CoreFreePool (AdjacentEntry
);
444 CoreCleanupGcdMapEntry (
445 IN EFI_GCD_MAP_ENTRY
*TopEntry
,
446 IN EFI_GCD_MAP_ENTRY
*BottomEntry
,
447 IN LIST_ENTRY
*StartLink
,
448 IN LIST_ENTRY
*EndLink
,
455 Merge adjacent entries on total chain.
459 TopEntry - Top entry of GCD map.
461 BottomEntry - Bottom entry of GCD map.
463 StartLink - Start link of the list for this loop.
465 EndLink - End link of the list for this loop.
471 EFI_SUCCESS - GCD map successfully cleaned up.
477 if (TopEntry
->Signature
== 0) {
478 CoreFreePool (TopEntry
);
480 if (BottomEntry
->Signature
== 0) {
481 CoreFreePool (BottomEntry
);
485 while (Link
!= EndLink
->ForwardLink
) {
486 CoreMergeGcdMapEntry (Link
, FALSE
, Map
);
487 Link
= Link
->ForwardLink
;
489 CoreMergeGcdMapEntry (EndLink
, TRUE
, Map
);
495 CoreSearchGcdMapEntry (
496 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
498 OUT LIST_ENTRY
**StartLink
,
499 OUT LIST_ENTRY
**EndLink
,
506 Search a segment of memory space in GCD map. The result is a range of GCD entry list.
510 BaseAddress - The start address of the segment.
512 Length - The length of the segment.
514 StartLink - The first GCD entry involves this segment of memory space.
516 EndLink - The first GCD entry involves this segment of memory space.
518 Map - Points to the start entry to search.
522 EFI_SUCCESS - Successfully found the entry.
524 EFI_NOT_FOUND - Not found.
529 EFI_GCD_MAP_ENTRY
*Entry
;
531 ASSERT (Length
!= 0);
536 Link
= Map
->ForwardLink
;
537 while (Link
!= Map
) {
538 Entry
= CR (Link
, EFI_GCD_MAP_ENTRY
, Link
, EFI_GCD_MAP_SIGNATURE
);
539 if (BaseAddress
>= Entry
->BaseAddress
&& BaseAddress
<= Entry
->EndAddress
) {
542 if (*StartLink
!= NULL
) {
543 if ((BaseAddress
+ Length
- 1) >= Entry
->BaseAddress
&&
544 (BaseAddress
+ Length
- 1) <= Entry
->EndAddress
) {
549 Link
= Link
->ForwardLink
;
551 return EFI_NOT_FOUND
;
555 CoreCountGcdMapEntry (
562 Count the amount of GCD map entries.
566 Map - Points to the start entry to do the count loop.
578 Link
= Map
->ForwardLink
;
579 while (Link
!= Map
) {
581 Link
= Link
->ForwardLink
;
589 ConverToCpuArchAttributes (
596 Return the memory attribute specified by Attributes
600 Attributes - A num with some attribute bits on.
604 The enum value of memory attribute.
608 if ( (Attributes
& EFI_MEMORY_UC
) == EFI_MEMORY_UC
) {
609 return EFI_MEMORY_UC
;
612 if ( (Attributes
& EFI_MEMORY_WC
) == EFI_MEMORY_WC
) {
613 return EFI_MEMORY_WC
;
616 if ( (Attributes
& EFI_MEMORY_WT
) == EFI_MEMORY_WT
) {
617 return EFI_MEMORY_WT
;
620 if ( (Attributes
& EFI_MEMORY_WB
) == EFI_MEMORY_WB
) {
621 return EFI_MEMORY_WB
;
624 if ( (Attributes
& EFI_MEMORY_WP
) == EFI_MEMORY_WP
) {
625 return EFI_MEMORY_WP
;
628 return INVALID_CPU_ARCH_ATTRIBUTES
;
636 IN EFI_GCD_MEMORY_TYPE GcdMemoryType
,
637 IN EFI_GCD_IO_TYPE GcdIoType
,
638 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
640 IN UINT64 Capabilities
,
647 Do operation on a segment of memory space specified (add, free, remove, change attribute ...).
651 Operation - The type of the operation
653 GcdMemoryType - Additional information for the operation
655 GcdIoType - Additional information for the operation
657 BaseAddress - Start address of the segment
659 Length - length of the segment
661 Capabilities - The alterable attributes of a newly added entry
663 Attributes - The attributes needs to be set
667 EFI_INVALID_PARAMETER - Length is 0 or address (length) not aligned when setting attribute.
669 EFI_SUCCESS - Action successfully done.
671 EFI_UNSUPPORTED - Could not find the proper descriptor on this segment or
672 set an upsupported attribute.
674 EFI_ACCESS_DENIED - Operate on an space non-exist or is used for an image.
676 EFI_NOT_FOUND - Free a non-using space or remove a non-exist space, and so on.
678 EFI_OUT_OF_RESOURCES - No buffer could be allocated.
687 EFI_GCD_MAP_ENTRY
*Entry
;
688 EFI_GCD_MAP_ENTRY
*TopEntry
;
689 EFI_GCD_MAP_ENTRY
*BottomEntry
;
690 LIST_ENTRY
*StartLink
;
693 EFI_CPU_ARCH_PROTOCOL
*CpuArch
;
694 UINT64 CpuArchAttributes
;
697 return EFI_INVALID_PARAMETER
;
701 if (Operation
& GCD_MEMORY_SPACE_OPERATION
) {
702 CoreAcquireGcdMemoryLock ();
703 Map
= &mGcdMemorySpaceMap
;
705 if (Operation
& GCD_IO_SPACE_OPERATION
) {
706 CoreAcquireGcdIoLock ();
707 Map
= &mGcdIoSpaceMap
;
711 // Search for the list of descriptors that cover the range BaseAddress to BaseAddress+Length
713 Status
= CoreSearchGcdMapEntry (BaseAddress
, Length
, &StartLink
, &EndLink
, Map
);
714 if (EFI_ERROR (Status
)) {
715 Status
= EFI_UNSUPPORTED
;
721 // Verify that the list of descriptors are unallocated non-existent memory.
724 while (Link
!= EndLink
->ForwardLink
) {
725 Entry
= CR (Link
, EFI_GCD_MAP_ENTRY
, Link
, EFI_GCD_MAP_SIGNATURE
);
730 case GCD_ADD_MEMORY_OPERATION
:
731 if (Entry
->GcdMemoryType
!= EfiGcdMemoryTypeNonExistent
||
732 Entry
->ImageHandle
!= NULL
) {
733 Status
= EFI_ACCESS_DENIED
;
737 case GCD_ADD_IO_OPERATION
:
738 if (Entry
->GcdIoType
!= EfiGcdIoTypeNonExistent
||
739 Entry
->ImageHandle
!= NULL
) {
740 Status
= EFI_ACCESS_DENIED
;
747 case GCD_FREE_MEMORY_OPERATION
:
748 case GCD_FREE_IO_OPERATION
:
749 if (Entry
->ImageHandle
== NULL
) {
750 Status
= EFI_NOT_FOUND
;
757 case GCD_REMOVE_MEMORY_OPERATION
:
758 if (Entry
->GcdMemoryType
== EfiGcdMemoryTypeNonExistent
) {
759 Status
= EFI_NOT_FOUND
;
762 if (Entry
->ImageHandle
!= NULL
) {
763 Status
= EFI_ACCESS_DENIED
;
767 case GCD_REMOVE_IO_OPERATION
:
768 if (Entry
->GcdIoType
== EfiGcdIoTypeNonExistent
) {
769 Status
= EFI_NOT_FOUND
;
772 if (Entry
->ImageHandle
!= NULL
) {
773 Status
= EFI_ACCESS_DENIED
;
778 // Set attribute operations
780 case GCD_SET_ATTRIBUTES_MEMORY_OPERATION
:
781 if (Attributes
& EFI_MEMORY_RUNTIME
) {
782 if ((BaseAddress
& EFI_PAGE_MASK
) != 0 || (Length
& EFI_PAGE_MASK
) != 0) {
783 Status
= EFI_INVALID_PARAMETER
;
788 if ((Entry
->Capabilities
& Attributes
) != Attributes
) {
789 Status
= EFI_UNSUPPORTED
;
794 Link
= Link
->ForwardLink
;
798 // Allocate work space to perform this operation
800 Status
= CoreAllocateGcdMapEntry (&TopEntry
, &BottomEntry
);
801 if (EFI_ERROR (Status
)) {
802 Status
= EFI_OUT_OF_RESOURCES
;
809 if (Operation
== GCD_SET_ATTRIBUTES_MEMORY_OPERATION
) {
811 // Call CPU Arch Protocol to attempt to set attributes on the range
813 CpuArchAttributes
= ConverToCpuArchAttributes (Attributes
);
814 if ( CpuArchAttributes
!= INVALID_CPU_ARCH_ATTRIBUTES
) {
815 Status
= CoreLocateProtocol (&gEfiCpuArchProtocolGuid
, NULL
, (VOID
**)&CpuArch
);
816 if (EFI_ERROR (Status
)) {
817 Status
= EFI_ACCESS_DENIED
;
821 Status
= CpuArch
->SetMemoryAttributes (
827 if (EFI_ERROR (Status
)) {
835 // Convert/Insert the list of descriptors from StartLink to EndLink
838 while (Link
!= EndLink
->ForwardLink
) {
839 Entry
= CR (Link
, EFI_GCD_MAP_ENTRY
, Link
, EFI_GCD_MAP_SIGNATURE
);
840 CoreInsertGcdMapEntry (Link
, Entry
, BaseAddress
, Length
, TopEntry
, BottomEntry
);
845 case GCD_ADD_MEMORY_OPERATION
:
846 Entry
->GcdMemoryType
= GcdMemoryType
;
847 if (GcdMemoryType
== EfiGcdMemoryTypeMemoryMappedIo
) {
848 Entry
->Capabilities
= Capabilities
| EFI_MEMORY_RUNTIME
| EFI_MEMORY_PORT_IO
;
850 Entry
->Capabilities
= Capabilities
| EFI_MEMORY_RUNTIME
;
853 case GCD_ADD_IO_OPERATION
:
854 Entry
->GcdIoType
= GcdIoType
;
859 case GCD_FREE_MEMORY_OPERATION
:
860 case GCD_FREE_IO_OPERATION
:
861 Entry
->ImageHandle
= NULL
;
862 Entry
->DeviceHandle
= NULL
;
867 case GCD_REMOVE_MEMORY_OPERATION
:
868 Entry
->GcdMemoryType
= EfiGcdMemoryTypeNonExistent
;
869 Entry
->Capabilities
= 0;
871 case GCD_REMOVE_IO_OPERATION
:
872 Entry
->GcdIoType
= EfiGcdIoTypeNonExistent
;
875 // Set attribute operations
877 case GCD_SET_ATTRIBUTES_MEMORY_OPERATION
:
878 Entry
->Attributes
= Attributes
;
881 Link
= Link
->ForwardLink
;
887 Status
= CoreCleanupGcdMapEntry (TopEntry
, BottomEntry
, StartLink
, EndLink
, Map
);
890 if (Operation
& GCD_MEMORY_SPACE_OPERATION
) {
891 CoreReleaseGcdMemoryLock ();
893 if (Operation
& GCD_IO_SPACE_OPERATION
) {
894 CoreReleaseGcdIoLock ();
901 CoreAllocateSpaceCheckEntry (
903 IN EFI_GCD_MAP_ENTRY
*Entry
,
904 IN EFI_GCD_MEMORY_TYPE GcdMemoryType
,
905 IN EFI_GCD_IO_TYPE GcdIoType
911 Check whether an entry could be used to allocate space.
915 Operation - Allocate memory or IO
917 Entry - The entry to be tested
919 GcdMemoryType - The desired memory type
921 GcdIoType - The desired IO type
925 EFI_NOT_FOUND - The memory type does not match or there's an image handle on the entry.
927 EFI_UNSUPPORTED - The operation unsupported.
929 EFI_SUCCESS - It's ok for this entry to be used to allocate space.
933 if (Entry
->ImageHandle
!= NULL
) {
934 return EFI_NOT_FOUND
;
937 case GCD_ALLOCATE_MEMORY_OPERATION
:
938 if (Entry
->GcdMemoryType
!= GcdMemoryType
) {
939 return EFI_NOT_FOUND
;
942 case GCD_ALLOCATE_IO_OPERATION
:
943 if (Entry
->GcdIoType
!= GcdIoType
) {
944 return EFI_NOT_FOUND
;
948 return EFI_UNSUPPORTED
;
956 IN EFI_GCD_ALLOCATE_TYPE GcdAllocateType
,
957 IN EFI_GCD_MEMORY_TYPE GcdMemoryType
,
958 IN EFI_GCD_IO_TYPE GcdIoType
,
961 IN OUT EFI_PHYSICAL_ADDRESS
*BaseAddress
,
962 IN EFI_HANDLE ImageHandle
,
963 IN EFI_HANDLE DeviceHandle OPTIONAL
969 Allocate space on specified address and length.
973 Operation - The type of operation (memory or IO)
975 GcdAllocateType - The type of allocate operation
977 GcdMemoryType - The desired memory type
979 GcdIoType - The desired IO type
981 Alignment - Align with 2^Alignment
983 Length - Length to allocate
985 BaseAddress - Base address to allocate
987 ImageHandle - The image handle consume the allocated space.
989 DeviceHandle - The device handle consume the allocated space.
993 EFI_INVALID_PARAMETER - Invalid parameter.
995 EFI_NOT_FOUND - No descriptor for the desired space exists.
997 EFI_SUCCESS - Space successfully allocated.
1002 EFI_PHYSICAL_ADDRESS AlignmentMask
;
1003 EFI_PHYSICAL_ADDRESS MaxAddress
;
1006 LIST_ENTRY
*SubLink
;
1007 EFI_GCD_MAP_ENTRY
*Entry
;
1008 EFI_GCD_MAP_ENTRY
*TopEntry
;
1009 EFI_GCD_MAP_ENTRY
*BottomEntry
;
1010 LIST_ENTRY
*StartLink
;
1011 LIST_ENTRY
*EndLink
;
1015 // Make sure parameters are valid
1017 if (GcdAllocateType
< 0 || GcdAllocateType
>= EfiGcdMaxAllocateType
) {
1018 return EFI_INVALID_PARAMETER
;
1020 if (GcdMemoryType
< 0 || GcdMemoryType
>= EfiGcdMemoryTypeMaximum
) {
1021 return EFI_INVALID_PARAMETER
;
1023 if (GcdIoType
< 0 || GcdIoType
>= EfiGcdIoTypeMaximum
) {
1024 return EFI_INVALID_PARAMETER
;
1026 if (BaseAddress
== NULL
) {
1027 return EFI_INVALID_PARAMETER
;
1029 if (ImageHandle
== NULL
) {
1030 return EFI_INVALID_PARAMETER
;
1032 if (Alignment
>= 64) {
1033 return EFI_NOT_FOUND
;
1036 return EFI_INVALID_PARAMETER
;
1040 if (Operation
& GCD_MEMORY_SPACE_OPERATION
) {
1041 CoreAcquireGcdMemoryLock ();
1042 Map
= &mGcdMemorySpaceMap
;
1044 if (Operation
& GCD_IO_SPACE_OPERATION
) {
1045 CoreAcquireGcdIoLock ();
1046 Map
= &mGcdIoSpaceMap
;
1053 // Compute alignment bit mask
1055 AlignmentMask
= LShiftU64 (1, Alignment
) - 1;
1057 if (GcdAllocateType
== EfiGcdAllocateAddress
) {
1059 // Verify that the BaseAddress passed in is aligned correctly
1061 if ((*BaseAddress
& AlignmentMask
) != 0) {
1062 Status
= EFI_NOT_FOUND
;
1067 // Search for the list of descriptors that cover the range BaseAddress to BaseAddress+Length
1069 Status
= CoreSearchGcdMapEntry (*BaseAddress
, Length
, &StartLink
, &EndLink
, Map
);
1070 if (EFI_ERROR (Status
)) {
1071 Status
= EFI_NOT_FOUND
;
1076 // Verify that the list of descriptors are unallocated memory matching GcdMemoryType.
1079 while (Link
!= EndLink
->ForwardLink
) {
1080 Entry
= CR (Link
, EFI_GCD_MAP_ENTRY
, Link
, EFI_GCD_MAP_SIGNATURE
);
1081 Link
= Link
->ForwardLink
;
1082 Status
= CoreAllocateSpaceCheckEntry (Operation
, Entry
, GcdMemoryType
, GcdIoType
);
1083 if (EFI_ERROR (Status
)) {
1090 Entry
= CR (Map
->BackLink
, EFI_GCD_MAP_ENTRY
, Link
, EFI_GCD_MAP_SIGNATURE
);
1093 // Compute the maximum address to use in the search algorithm
1095 if (GcdAllocateType
== EfiGcdAllocateMaxAddressSearchBottomUp
||
1096 GcdAllocateType
== EfiGcdAllocateMaxAddressSearchTopDown
) {
1097 MaxAddress
= *BaseAddress
;
1099 MaxAddress
= Entry
->EndAddress
;
1103 // Verify that the list of descriptors are unallocated memory matching GcdMemoryType.
1105 if (GcdAllocateType
== EfiGcdAllocateMaxAddressSearchTopDown
||
1106 GcdAllocateType
== EfiGcdAllocateAnySearchTopDown
) {
1107 Link
= Map
->BackLink
;
1109 Link
= Map
->ForwardLink
;
1111 while (Link
!= Map
) {
1112 Entry
= CR (Link
, EFI_GCD_MAP_ENTRY
, Link
, EFI_GCD_MAP_SIGNATURE
);
1114 if (GcdAllocateType
== EfiGcdAllocateMaxAddressSearchTopDown
||
1115 GcdAllocateType
== EfiGcdAllocateAnySearchTopDown
) {
1116 Link
= Link
->BackLink
;
1118 Link
= Link
->ForwardLink
;
1121 Status
= CoreAllocateSpaceCheckEntry (Operation
, Entry
, GcdMemoryType
, GcdIoType
);
1122 if (EFI_ERROR (Status
)) {
1126 if (GcdAllocateType
== EfiGcdAllocateMaxAddressSearchTopDown
||
1127 GcdAllocateType
== EfiGcdAllocateAnySearchTopDown
) {
1128 if ((Entry
->BaseAddress
+ Length
) > MaxAddress
) {
1131 if (Length
> (Entry
->EndAddress
+ 1)) {
1132 Status
= EFI_NOT_FOUND
;
1135 if (Entry
->EndAddress
> MaxAddress
) {
1136 *BaseAddress
= MaxAddress
;
1138 *BaseAddress
= Entry
->EndAddress
;
1140 *BaseAddress
= (*BaseAddress
+ 1 - Length
) & (~AlignmentMask
);
1142 *BaseAddress
= (Entry
->BaseAddress
+ AlignmentMask
) & (~AlignmentMask
);
1143 if ((*BaseAddress
+ Length
- 1) > MaxAddress
) {
1144 Status
= EFI_NOT_FOUND
;
1150 // Search for the list of descriptors that cover the range BaseAddress to BaseAddress+Length
1152 Status
= CoreSearchGcdMapEntry (*BaseAddress
, Length
, &StartLink
, &EndLink
, Map
);
1153 if (EFI_ERROR (Status
)) {
1154 Status
= EFI_NOT_FOUND
;
1160 // Verify that the list of descriptors are unallocated memory matching GcdMemoryType.
1163 SubLink
= StartLink
;
1164 while (SubLink
!= EndLink
->ForwardLink
) {
1165 Entry
= CR (SubLink
, EFI_GCD_MAP_ENTRY
, Link
, EFI_GCD_MAP_SIGNATURE
);
1166 Status
= CoreAllocateSpaceCheckEntry (Operation
, Entry
, GcdMemoryType
, GcdIoType
);
1167 if (EFI_ERROR (Status
)) {
1172 SubLink
= SubLink
->ForwardLink
;
1180 Status
= EFI_NOT_FOUND
;
1185 // Allocate work space to perform this operation
1187 Status
= CoreAllocateGcdMapEntry (&TopEntry
, &BottomEntry
);
1188 if (EFI_ERROR (Status
)) {
1189 Status
= EFI_OUT_OF_RESOURCES
;
1194 // Convert/Insert the list of descriptors from StartLink to EndLink
1197 while (Link
!= EndLink
->ForwardLink
) {
1198 Entry
= CR (Link
, EFI_GCD_MAP_ENTRY
, Link
, EFI_GCD_MAP_SIGNATURE
);
1199 CoreInsertGcdMapEntry (Link
, Entry
, *BaseAddress
, Length
, TopEntry
, BottomEntry
);
1200 Entry
->ImageHandle
= ImageHandle
;
1201 Entry
->DeviceHandle
= DeviceHandle
;
1202 Link
= Link
->ForwardLink
;
1208 Status
= CoreCleanupGcdMapEntry (TopEntry
, BottomEntry
, StartLink
, EndLink
, Map
);
1211 if (Operation
& GCD_MEMORY_SPACE_OPERATION
) {
1212 CoreReleaseGcdMemoryLock ();
1214 if (Operation
& GCD_IO_SPACE_OPERATION
) {
1215 CoreReleaseGcdIoLock ();
1223 CoreInternalAddMemorySpace (
1224 IN EFI_GCD_MEMORY_TYPE GcdMemoryType
,
1225 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
1227 IN UINT64 Capabilities
1231 Routine Description:
1233 Add a segment of memory to GCD map.
1237 GcdMemoryType - Memory type of the segment.
1239 BaseAddress - Base address of the segment.
1241 Length - Length of the segment.
1243 Capabilities - alterable attributes of the segment.
1247 EFI_INVALID_PARAMETER - Invalid parameters.
1249 EFI_SUCCESS - Successfully add a segment of memory space.
1254 // Make sure parameters are valid
1256 if (GcdMemoryType
<= EfiGcdMemoryTypeNonExistent
|| GcdMemoryType
>= EfiGcdMemoryTypeMaximum
) {
1257 return EFI_INVALID_PARAMETER
;
1260 return CoreConvertSpace (GCD_ADD_MEMORY_OPERATION
, GcdMemoryType
, 0, BaseAddress
, Length
, Capabilities
, 0);
1264 // GCD Core Services
1267 CoreAllocateMemorySpace (
1268 IN EFI_GCD_ALLOCATE_TYPE GcdAllocateType
,
1269 IN EFI_GCD_MEMORY_TYPE GcdMemoryType
,
1272 IN OUT EFI_PHYSICAL_ADDRESS
*BaseAddress
,
1273 IN EFI_HANDLE ImageHandle
,
1274 IN EFI_HANDLE DeviceHandle OPTIONAL
1278 Routine Description:
1280 Allocates nonexistent memory, reserved memory, system memory, or memorymapped
1281 I/O resources from the global coherency domain of the processor.
1285 GcdAllocateType - The type of allocate operation
1287 GcdMemoryType - The desired memory type
1289 Alignment - Align with 2^Alignment
1291 Length - Length to allocate
1293 BaseAddress - Base address to allocate
1295 ImageHandle - The image handle consume the allocated space.
1297 DeviceHandle - The device handle consume the allocated space.
1301 EFI_INVALID_PARAMETER - Invalid parameter.
1303 EFI_NOT_FOUND - No descriptor contains the desired space.
1305 EFI_SUCCESS - Memory space successfully allocated.
1309 return CoreAllocateSpace (
1310 GCD_ALLOCATE_MEMORY_OPERATION
,
1323 CoreAddMemorySpace (
1324 IN EFI_GCD_MEMORY_TYPE GcdMemoryType
,
1325 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
1327 IN UINT64 Capabilities
1331 Routine Description:
1333 Adds reserved memory, system memory, or memory-mapped I/O resources to the
1334 global coherency domain of the processor.
1338 GcdMemoryType - Memory type of the memory space.
1340 BaseAddress - Base address of the memory space.
1342 Length - Length of the memory space.
1344 Capabilities - alterable attributes of the memory space.
1348 EFI_SUCCESS - Merged this memory space into GCD map.
1353 EFI_PHYSICAL_ADDRESS PageBaseAddress
;
1356 Status
= CoreInternalAddMemorySpace (GcdMemoryType
, BaseAddress
, Length
, Capabilities
);
1358 if (!EFI_ERROR (Status
) && GcdMemoryType
== EfiGcdMemoryTypeSystemMemory
) {
1360 PageBaseAddress
= PageAlignLength (BaseAddress
);
1361 PageLength
= PageAlignLength (BaseAddress
+ Length
- PageBaseAddress
);
1363 Status
= CoreAllocateMemorySpace (
1364 EfiGcdAllocateAddress
,
1369 gDxeCoreImageHandle
,
1373 if (!EFI_ERROR (Status
)) {
1374 CoreAddMemoryDescriptor (
1375 EfiConventionalMemory
,
1377 RShiftU64 (PageLength
, EFI_PAGE_SHIFT
),
1381 for (; PageLength
!= 0; PageLength
-= EFI_PAGE_SIZE
, PageBaseAddress
+= EFI_PAGE_SIZE
) {
1382 Status
= CoreAllocateMemorySpace (
1383 EfiGcdAllocateAddress
,
1388 gDxeCoreImageHandle
,
1392 if (!EFI_ERROR (Status
)) {
1393 CoreAddMemoryDescriptor (
1394 EfiConventionalMemory
,
1407 CoreFreeMemorySpace (
1408 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
1413 Routine Description:
1415 Frees nonexistent memory, reserved memory, system memory, or memory-mapped
1416 I/O resources from the global coherency domain of the processor.
1420 BaseAddress - Base address of the memory space.
1422 Length - Length of the memory space.
1426 EFI_SUCCESS - Space successfully freed.
1430 return CoreConvertSpace (GCD_FREE_MEMORY_OPERATION
, 0, 0, BaseAddress
, Length
, 0, 0);
1434 CoreRemoveMemorySpace (
1435 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
1440 Routine Description:
1442 Removes reserved memory, system memory, or memory-mapped I/O resources from
1443 the global coherency domain of the processor.
1447 BaseAddress - Base address of the memory space.
1449 Length - Length of the memory space.
1453 EFI_SUCCESS - Successfully remove a segment of memory space.
1457 return CoreConvertSpace (GCD_REMOVE_MEMORY_OPERATION
, 0, 0, BaseAddress
, Length
, 0, 0);
1461 BuildMemoryDescriptor (
1462 IN OUT EFI_GCD_MEMORY_SPACE_DESCRIPTOR
*Descriptor
,
1463 IN EFI_GCD_MAP_ENTRY
*Entry
1467 Routine Description:
1469 Build a memory descriptor according to an entry.
1473 Descriptor - The descriptor to be built
1475 Entry - According to this entry
1483 Descriptor
->BaseAddress
= Entry
->BaseAddress
;
1484 Descriptor
->Length
= Entry
->EndAddress
- Entry
->BaseAddress
+ 1;
1485 Descriptor
->Capabilities
= Entry
->Capabilities
;
1486 Descriptor
->Attributes
= Entry
->Attributes
;
1487 Descriptor
->GcdMemoryType
= Entry
->GcdMemoryType
;
1488 Descriptor
->ImageHandle
= Entry
->ImageHandle
;
1489 Descriptor
->DeviceHandle
= Entry
->DeviceHandle
;
1493 CoreGetMemorySpaceDescriptor (
1494 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
1495 OUT EFI_GCD_MEMORY_SPACE_DESCRIPTOR
*Descriptor
1499 Routine Description:
1501 Retrieves the descriptor for a memory region containing a specified address.
1505 BaseAddress - Specified start address
1507 Descriptor - Specified length
1511 EFI_INVALID_PARAMETER - Invalid parameter
1513 EFI_SUCCESS - Successfully get memory space descriptor.
1518 LIST_ENTRY
*StartLink
;
1519 LIST_ENTRY
*EndLink
;
1520 EFI_GCD_MAP_ENTRY
*Entry
;
1523 // Make sure parameters are valid
1525 if (Descriptor
== NULL
) {
1526 return EFI_INVALID_PARAMETER
;
1529 CoreAcquireGcdMemoryLock ();
1532 // Search for the list of descriptors that contain BaseAddress
1534 Status
= CoreSearchGcdMapEntry (BaseAddress
, 1, &StartLink
, &EndLink
, &mGcdMemorySpaceMap
);
1535 if (EFI_ERROR (Status
)) {
1536 Status
= EFI_NOT_FOUND
;
1539 // Copy the contents of the found descriptor into Descriptor
1541 Entry
= CR (StartLink
, EFI_GCD_MAP_ENTRY
, Link
, EFI_GCD_MAP_SIGNATURE
);
1542 BuildMemoryDescriptor (Descriptor
, Entry
);
1545 CoreReleaseGcdMemoryLock ();
1551 CoreSetMemorySpaceAttributes (
1552 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
1554 IN UINT64 Attributes
1558 Routine Description:
1560 Modifies the attributes for a memory region in the global coherency domain of the
1565 BaseAddress - Specified start address
1567 Length - Specified length
1569 Attributes - Specified attributes
1573 EFI_SUCCESS - Successfully set attribute of a segment of memory space.
1577 return CoreConvertSpace (GCD_SET_ATTRIBUTES_MEMORY_OPERATION
, 0, 0, BaseAddress
, Length
, 0, Attributes
);
1581 CoreGetMemorySpaceMap (
1582 OUT UINTN
*NumberOfDescriptors
,
1583 OUT EFI_GCD_MEMORY_SPACE_DESCRIPTOR
**MemorySpaceMap
1587 Routine Description:
1589 Returns a map of the memory resources in the global coherency domain of the
1594 NumberOfDescriptors - Number of descriptors.
1596 MemorySpaceMap - Descriptor array
1600 EFI_INVALID_PARAMETER - Invalid parameter
1602 EFI_OUT_OF_RESOURCES - No enough buffer to allocate
1604 EFI_SUCCESS - Successfully get memory space map.
1610 EFI_GCD_MAP_ENTRY
*Entry
;
1611 EFI_GCD_MEMORY_SPACE_DESCRIPTOR
*Descriptor
;
1614 // Make sure parameters are valid
1616 if (NumberOfDescriptors
== NULL
) {
1617 return EFI_INVALID_PARAMETER
;
1619 if (MemorySpaceMap
== NULL
) {
1620 return EFI_INVALID_PARAMETER
;
1623 CoreAcquireGcdMemoryLock ();
1626 // Count the number of descriptors
1628 *NumberOfDescriptors
= CoreCountGcdMapEntry (&mGcdMemorySpaceMap
);
1631 // Allocate the MemorySpaceMap
1633 *MemorySpaceMap
= CoreAllocateBootServicesPool (*NumberOfDescriptors
* sizeof (EFI_GCD_MEMORY_SPACE_DESCRIPTOR
));
1634 if (*MemorySpaceMap
== NULL
) {
1635 Status
= EFI_OUT_OF_RESOURCES
;
1640 // Fill in the MemorySpaceMap
1642 Descriptor
= *MemorySpaceMap
;
1643 Link
= mGcdMemorySpaceMap
.ForwardLink
;
1644 while (Link
!= &mGcdMemorySpaceMap
) {
1645 Entry
= CR (Link
, EFI_GCD_MAP_ENTRY
, Link
, EFI_GCD_MAP_SIGNATURE
);
1646 BuildMemoryDescriptor (Descriptor
, Entry
);
1648 Link
= Link
->ForwardLink
;
1650 Status
= EFI_SUCCESS
;
1653 CoreReleaseGcdMemoryLock ();
1659 IN EFI_GCD_IO_TYPE GcdIoType
,
1660 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
1665 Routine Description:
1667 Adds reserved I/O or I/O resources to the global coherency domain of the processor.
1671 GcdIoType - IO type of the segment.
1673 BaseAddress - Base address of the segment.
1675 Length - Length of the segment.
1679 EFI_SUCCESS - Merged this segment into GCD map.
1680 EFI_INVALID_PARAMETER - Parameter not valid
1685 // Make sure parameters are valid
1687 if (GcdIoType
<= EfiGcdIoTypeNonExistent
|| GcdIoType
>= EfiGcdIoTypeMaximum
) {
1688 return EFI_INVALID_PARAMETER
;
1690 return CoreConvertSpace (GCD_ADD_IO_OPERATION
, 0, GcdIoType
, BaseAddress
, Length
, 0, 0);
1694 CoreAllocateIoSpace (
1695 IN EFI_GCD_ALLOCATE_TYPE GcdAllocateType
,
1696 IN EFI_GCD_IO_TYPE GcdIoType
,
1699 IN OUT EFI_PHYSICAL_ADDRESS
*BaseAddress
,
1700 IN EFI_HANDLE ImageHandle
,
1701 IN EFI_HANDLE DeviceHandle OPTIONAL
1705 Routine Description:
1707 Allocates nonexistent I/O, reserved I/O, or I/O resources from the global coherency
1708 domain of the processor.
1712 GcdAllocateType - The type of allocate operation
1714 GcdIoType - The desired IO type
1716 Alignment - Align with 2^Alignment
1718 Length - Length to allocate
1720 BaseAddress - Base address to allocate
1722 ImageHandle - The image handle consume the allocated space.
1724 DeviceHandle - The device handle consume the allocated space.
1728 EFI_INVALID_PARAMETER - Invalid parameter.
1730 EFI_NOT_FOUND - No descriptor contains the desired space.
1732 EFI_SUCCESS - IO space successfully allocated.
1736 return CoreAllocateSpace (
1737 GCD_ALLOCATE_IO_OPERATION
,
1751 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
1756 Routine Description:
1758 Frees nonexistent I/O, reserved I/O, or I/O resources from the global coherency
1759 domain of the processor.
1763 BaseAddress - Base address of the segment.
1765 Length - Length of the segment.
1769 EFI_SUCCESS - Space successfully freed.
1773 return CoreConvertSpace (GCD_FREE_IO_OPERATION
, 0, 0, BaseAddress
, Length
, 0, 0);
1778 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
1783 Routine Description:
1785 Removes reserved I/O or I/O resources from the global coherency domain of the
1790 BaseAddress - Base address of the segment.
1792 Length - Length of the segment.
1796 EFI_SUCCESS - Successfully removed a segment of IO space.
1800 return CoreConvertSpace (GCD_REMOVE_IO_OPERATION
, 0, 0, BaseAddress
, Length
, 0, 0);
1805 IN EFI_GCD_IO_SPACE_DESCRIPTOR
*Descriptor
,
1806 IN EFI_GCD_MAP_ENTRY
*Entry
1810 Routine Description:
1812 Build a IO descriptor according to an entry.
1816 Descriptor - The descriptor to be built
1818 Entry - According to this entry
1826 Descriptor
->BaseAddress
= Entry
->BaseAddress
;
1827 Descriptor
->Length
= Entry
->EndAddress
- Entry
->BaseAddress
+ 1;
1828 Descriptor
->GcdIoType
= Entry
->GcdIoType
;
1829 Descriptor
->ImageHandle
= Entry
->ImageHandle
;
1830 Descriptor
->DeviceHandle
= Entry
->DeviceHandle
;
1834 CoreGetIoSpaceDescriptor (
1835 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
1836 OUT EFI_GCD_IO_SPACE_DESCRIPTOR
*Descriptor
1840 Routine Description:
1842 Retrieves the descriptor for an I/O region containing a specified address.
1846 BaseAddress - Specified start address
1848 Descriptor - Specified length
1852 EFI_INVALID_PARAMETER - Descriptor is NULL.
1854 EFI_SUCCESS - Successfully get the IO space 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
;
1880 // Copy the contents of the found descriptor into Descriptor
1882 Entry
= CR (StartLink
, EFI_GCD_MAP_ENTRY
, Link
, EFI_GCD_MAP_SIGNATURE
);
1883 BuildIoDescriptor (Descriptor
, Entry
);
1886 CoreReleaseGcdIoLock ();
1893 OUT UINTN
*NumberOfDescriptors
,
1894 OUT EFI_GCD_IO_SPACE_DESCRIPTOR
**IoSpaceMap
1898 Routine Description:
1900 Returns a map of the I/O resources in the global coherency domain of the processor.
1904 NumberOfDescriptors - Number of descriptors.
1906 IoSpaceMap - Descriptor array
1910 EFI_INVALID_PARAMETER - Invalid parameter
1912 EFI_OUT_OF_RESOURCES - No enough buffer to allocate
1914 EFI_SUCCESS - Successfully get IO space map.
1920 EFI_GCD_MAP_ENTRY
*Entry
;
1921 EFI_GCD_IO_SPACE_DESCRIPTOR
*Descriptor
;
1924 // Make sure parameters are valid
1926 if (NumberOfDescriptors
== NULL
) {
1927 return EFI_INVALID_PARAMETER
;
1929 if (IoSpaceMap
== NULL
) {
1930 return EFI_INVALID_PARAMETER
;
1933 CoreAcquireGcdIoLock ();
1936 // Count the number of descriptors
1938 *NumberOfDescriptors
= CoreCountGcdMapEntry (&mGcdIoSpaceMap
);
1941 // Allocate the IoSpaceMap
1943 *IoSpaceMap
= CoreAllocateBootServicesPool (*NumberOfDescriptors
* sizeof (EFI_GCD_IO_SPACE_DESCRIPTOR
));
1944 if (*IoSpaceMap
== NULL
) {
1945 Status
= EFI_OUT_OF_RESOURCES
;
1950 // Fill in the IoSpaceMap
1952 Descriptor
= *IoSpaceMap
;
1953 Link
= mGcdIoSpaceMap
.ForwardLink
;
1954 while (Link
!= &mGcdIoSpaceMap
) {
1955 Entry
= CR (Link
, EFI_GCD_MAP_ENTRY
, Link
, EFI_GCD_MAP_SIGNATURE
);
1956 BuildIoDescriptor (Descriptor
, Entry
);
1958 Link
= Link
->ForwardLink
;
1960 Status
= EFI_SUCCESS
;
1963 CoreReleaseGcdIoLock ();
1968 CoreConvertResourceDescriptorHobAttributesToCapabilities (
1969 EFI_GCD_MEMORY_TYPE GcdMemoryType
,
1974 Routine Description:
1976 Converts a Resource Descriptor HOB attributes mask to an EFI Memory Descriptor
1981 GcdMemoryType - Type of resource in the GCD memory map.
1982 Attributes - The attribute mask in the Resource Descriptor HOB.
1986 The capabilities mask for an EFI Memory Descriptor.
1990 UINT64 Capabilities
;
1991 GCD_ATTRIBUTE_CONVERSION_ENTRY
*Conversion
;
1994 // Convert the Resource HOB Attributes to an EFI Memory Capabilities mask
1996 for (Capabilities
= 0, Conversion
= mAttributeConversionTable
; Conversion
->Attribute
!= 0; Conversion
++) {
1997 if (Conversion
->Memory
|| (GcdMemoryType
!= EfiGcdMemoryTypeSystemMemory
)) {
1998 if (Attributes
& Conversion
->Attribute
) {
1999 Capabilities
|= Conversion
->Capability
;
2004 return Capabilities
;
2008 CoreInitializeMemoryServices (
2010 OUT EFI_PHYSICAL_ADDRESS
*MemoryBaseAddress
,
2011 OUT UINT64
*MemoryLength
2015 Routine Description:
2017 External function. Initializes the GCD and memory services based on the memory
2018 descriptor HOBs. This function is responsible for priming the GCD map and the
2019 memory map, so memory allocations and resource allocations can be made. The first
2020 part of this function can not depend on any memory services until at least one
2021 memory descriptor is provided to the memory services. Then the memory services
2022 can be used to intialize the GCD map.
2026 HobStart - The start address of the HOB.
2027 MemoryBaseAddress - Start address of memory region found to init DXE core.
2028 MemoryLength - Length of memory region found to init DXE core.
2032 EFI_SUCCESS - Memory services successfully initialized.
2036 EFI_PEI_HOB_POINTERS Hob
;
2037 EFI_MEMORY_TYPE_INFORMATION
*EfiMemoryTypeInformation
;
2040 EFI_HOB_HANDOFF_INFO_TABLE
*PhitHob
;
2041 EFI_HOB_RESOURCE_DESCRIPTOR
*ResourceHob
;
2042 EFI_HOB_RESOURCE_DESCRIPTOR
*PhitResourceHob
;
2043 EFI_PHYSICAL_ADDRESS BaseAddress
;
2046 UINT64 Capabilities
;
2047 EFI_PHYSICAL_ADDRESS MaxMemoryBaseAddress
;
2048 UINT64 MaxMemoryLength
;
2049 UINT64 MaxMemoryAttributes
;
2050 EFI_PHYSICAL_ADDRESS MaxAddress
;
2051 EFI_PHYSICAL_ADDRESS HighAddress
;
2052 EFI_HOB_RESOURCE_DESCRIPTOR
*MaxResourceHob
;
2053 EFI_HOB_GUID_TYPE
*GuidHob
;
2056 // Point at the first HOB. This must be the PHIT HOB.
2058 Hob
.Raw
= *HobStart
;
2059 ASSERT (GET_HOB_TYPE (Hob
) == EFI_HOB_TYPE_HANDOFF
);
2062 // Initialize the spin locks and maps in the memory services.
2063 // Also fill in the memory services into the EFI Boot Services Table
2065 CoreInitializePool ();
2068 // Initialize Local Variables
2070 PhitResourceHob
= NULL
;
2071 MaxResourceHob
= NULL
;
2076 MaxMemoryBaseAddress
= 0;
2077 MaxMemoryLength
= 0;
2078 MaxMemoryAttributes
= 0;
2081 // Cache the PHIT HOB for later use
2083 PhitHob
= Hob
.HandoffInformationTable
;
2086 // See if a Memory Type Information HOB is available
2088 GuidHob
= GetFirstGuidHob (&gEfiMemoryTypeInformationGuid
);
2089 if (GuidHob
!= NULL
) {
2090 EfiMemoryTypeInformation
= GET_GUID_HOB_DATA (GuidHob
);
2091 DataSize
= GET_GUID_HOB_DATA_SIZE (GuidHob
);
2092 if (EfiMemoryTypeInformation
!= NULL
&& DataSize
> 0 && DataSize
<= (EfiMaxMemoryType
+ 1) * sizeof (EFI_MEMORY_TYPE_INFORMATION
)) {
2093 CopyMem (&gMemoryTypeInformation
, EfiMemoryTypeInformation
, DataSize
);
2098 // Find the Resource Descriptor HOB that contains range FreeMemoryBaseAddress..FreeMemoryLength
2102 for (Hob
.Raw
= *HobStart
; !END_OF_HOB_LIST(Hob
); Hob
.Raw
= GET_NEXT_HOB(Hob
)) {
2104 if (GET_HOB_TYPE (Hob
) == EFI_HOB_TYPE_RESOURCE_DESCRIPTOR
) {
2106 ResourceHob
= Hob
.ResourceDescriptor
;
2108 if (ResourceHob
->ResourceType
== EFI_RESOURCE_SYSTEM_MEMORY
&&
2109 (ResourceHob
->ResourceAttribute
& MEMORY_ATTRIBUTE_MASK
) == TESTED_MEMORY_ATTRIBUTES
) {
2111 if (PhitHob
->EfiFreeMemoryBottom
>= ResourceHob
->PhysicalStart
&&
2112 PhitHob
->EfiFreeMemoryTop
<= (ResourceHob
->PhysicalStart
+ ResourceHob
->ResourceLength
) ) {
2115 // Cache the resource descriptor HOB for the memory region described by the PHIT HOB
2117 PhitResourceHob
= ResourceHob
;
2120 Attributes
= PhitResourceHob
->ResourceAttribute
;
2121 BaseAddress
= PageAlignAddress (PhitHob
->EfiMemoryTop
);
2122 Length
= PageAlignLength (ResourceHob
->PhysicalStart
+ ResourceHob
->ResourceLength
- BaseAddress
);
2123 if (Length
< MINIMUM_INITIAL_MEMORY_SIZE
) {
2124 BaseAddress
= PageAlignAddress (PhitHob
->EfiFreeMemoryBottom
);
2125 Length
= PageAlignLength (PhitHob
->EfiFreeMemoryTop
- BaseAddress
);
2126 if (Length
< MINIMUM_INITIAL_MEMORY_SIZE
) {
2127 BaseAddress
= PageAlignAddress (ResourceHob
->PhysicalStart
);
2128 Length
= PageAlignLength ((UINT64
)((UINTN
)*HobStart
- BaseAddress
));
2138 // Assert if a resource descriptor HOB for the memory region described by the PHIT was not found
2143 // Search all the resource descriptor HOBs from the highest possible addresses down for a memory
2144 // region that is big enough to initialize the DXE core. Always skip the PHIT Resource HOB.
2145 // The max address must be within the physically addressible range for the processor.
2147 MaxMemoryLength
= 0;
2148 MaxAddress
= EFI_MAX_ADDRESS
;
2153 // Search for a tested memory region that is below MaxAddress
2155 for (Hob
.Raw
= *HobStart
; !END_OF_HOB_LIST(Hob
); Hob
.Raw
= GET_NEXT_HOB(Hob
)) {
2158 // See if this is a resource descriptor HOB that does not contain the PHIT.
2160 if (Hob
.ResourceDescriptor
!= PhitResourceHob
&& GET_HOB_TYPE (Hob
) == EFI_HOB_TYPE_RESOURCE_DESCRIPTOR
) {
2162 ResourceHob
= Hob
.ResourceDescriptor
;
2164 // See if this resource descrior HOB describes tested system memory below MaxAddress
2166 if (ResourceHob
->ResourceType
== EFI_RESOURCE_SYSTEM_MEMORY
&&
2167 (ResourceHob
->ResourceAttribute
& MEMORY_ATTRIBUTE_MASK
) == TESTED_MEMORY_ATTRIBUTES
&&
2168 ResourceHob
->PhysicalStart
+ ResourceHob
->ResourceLength
<= MaxAddress
) {
2171 // See if this is the highest tested system memory region below MaxAddress
2173 if (ResourceHob
->PhysicalStart
> HighAddress
) {
2175 MaxResourceHob
= ResourceHob
;
2176 HighAddress
= MaxResourceHob
->PhysicalStart
;
2184 // Compute the size of the tested memory region below MaxAddrees
2186 MaxMemoryBaseAddress
= PageAlignAddress (MaxResourceHob
->PhysicalStart
);
2187 MaxMemoryLength
= PageAlignLength (MaxResourceHob
->PhysicalStart
+ MaxResourceHob
->ResourceLength
- MaxMemoryBaseAddress
);
2188 MaxMemoryAttributes
= MaxResourceHob
->ResourceAttribute
;
2190 MaxAddress
= ResourceHob
->PhysicalStart
;
2191 } while (Found
&& MaxMemoryLength
< MINIMUM_INITIAL_MEMORY_SIZE
);
2196 if ((Length
< MINIMUM_INITIAL_MEMORY_SIZE
) ||
2197 (MaxMemoryBaseAddress
> BaseAddress
&& MaxMemoryLength
>= MINIMUM_INITIAL_MEMORY_SIZE
) ) {
2198 BaseAddress
= MaxMemoryBaseAddress
;
2199 Length
= MaxMemoryLength
;
2200 Attributes
= MaxMemoryAttributes
;
2204 // If no memory regions are found that are big enough to initialize the DXE core, then ASSERT().
2206 ASSERT (Length
>= MINIMUM_INITIAL_MEMORY_SIZE
);
2209 // Convert the Resource HOB Attributes to an EFI Memory Capabilities mask
2211 Capabilities
= CoreConvertResourceDescriptorHobAttributesToCapabilities (EfiGcdMemoryTypeSystemMemory
, Attributes
);
2214 // Declare the very first memory region, so the EFI Memory Services are available.
2216 CoreAddMemoryDescriptor (
2217 EfiConventionalMemory
,
2219 RShiftU64 (Length
, EFI_PAGE_SHIFT
),
2223 *MemoryBaseAddress
= BaseAddress
;
2224 *MemoryLength
= Length
;
2230 CoreInitializeGcdServices (
2232 IN EFI_PHYSICAL_ADDRESS MemoryBaseAddress
,
2233 IN UINT64 MemoryLength
2237 Routine Description:
2239 External function. Initializes the GCD and memory services based on the memory
2240 descriptor HOBs. This function is responsible for priming the GCD map and the
2241 memory map, so memory allocations and resource allocations can be made. The first
2242 part of this function can not depend on any memory services until at least one
2243 memory descriptor is provided to the memory services. Then the memory services
2244 can be used to intialize the GCD map.
2248 HobStart - The start address of the HOB
2250 MemoryBaseAddress - Start address of memory region found to init DXE core.
2252 MemoryLength - Length of memory region found to init DXE core.
2257 EFI_SUCCESS - GCD services successfully initialized.
2261 EFI_PEI_HOB_POINTERS Hob
;
2263 EFI_HOB_HANDOFF_INFO_TABLE
*PhitHob
;
2264 UINT8 SizeOfMemorySpace
;
2265 UINT8 SizeOfIoSpace
;
2266 EFI_HOB_RESOURCE_DESCRIPTOR
*ResourceHob
;
2267 EFI_PHYSICAL_ADDRESS BaseAddress
;
2270 EFI_GCD_MAP_ENTRY
*Entry
;
2271 EFI_GCD_MEMORY_TYPE GcdMemoryType
;
2272 EFI_GCD_IO_TYPE GcdIoType
;
2273 EFI_GCD_MEMORY_SPACE_DESCRIPTOR Descriptor
;
2274 EFI_HOB_MEMORY_ALLOCATION
*MemoryHob
;
2275 EFI_HOB_FIRMWARE_VOLUME
*FirmwareVolumeHob
;
2276 UINTN NumberOfDescriptors
;
2277 EFI_GCD_MEMORY_SPACE_DESCRIPTOR
*MemorySpaceMap
;
2279 UINT64 Capabilities
;
2280 EFI_HOB_CPU
* CpuHob
;
2282 // Cache the PHIT HOB for later use
2284 PhitHob
= (EFI_HOB_HANDOFF_INFO_TABLE
*)(*HobStart
);
2287 // Get the number of address lines in the I/O and Memory space for the CPU
2289 CpuHob
= GetFirstHob (EFI_HOB_TYPE_CPU
);
2290 ASSERT (CpuHob
!= NULL
);
2291 SizeOfMemorySpace
= CpuHob
->SizeOfMemorySpace
;
2292 SizeOfIoSpace
= CpuHob
->SizeOfIoSpace
;
2295 // Initialize the GCD Memory Space Map
2297 Entry
= CoreAllocateCopyPool (sizeof (EFI_GCD_MAP_ENTRY
), &mGcdMemorySpaceMapEntryTemplate
);
2298 ASSERT (Entry
!= NULL
);
2300 Entry
->EndAddress
= LShiftU64 (1, SizeOfMemorySpace
) - 1;
2302 InsertHeadList (&mGcdMemorySpaceMap
, &Entry
->Link
);
2305 // Initialize the GCD I/O Space Map
2307 Entry
= CoreAllocateCopyPool (sizeof (EFI_GCD_MAP_ENTRY
), &mGcdIoSpaceMapEntryTemplate
);
2308 ASSERT (Entry
!= NULL
);
2310 Entry
->EndAddress
= LShiftU64 (1, SizeOfIoSpace
) - 1;
2312 InsertHeadList (&mGcdIoSpaceMap
, &Entry
->Link
);
2315 // Walk the HOB list and add all resource descriptors to the GCD
2317 for (Hob
.Raw
= *HobStart
; !END_OF_HOB_LIST(Hob
); Hob
.Raw
= GET_NEXT_HOB(Hob
)) {
2319 GcdMemoryType
= EfiGcdMemoryTypeNonExistent
;
2320 GcdIoType
= EfiGcdIoTypeNonExistent
;
2322 if (GET_HOB_TYPE (Hob
) == EFI_HOB_TYPE_RESOURCE_DESCRIPTOR
) {
2324 ResourceHob
= Hob
.ResourceDescriptor
;
2326 switch (ResourceHob
->ResourceType
) {
2327 case EFI_RESOURCE_SYSTEM_MEMORY
:
2328 if ((ResourceHob
->ResourceAttribute
& MEMORY_ATTRIBUTE_MASK
) == TESTED_MEMORY_ATTRIBUTES
) {
2329 GcdMemoryType
= EfiGcdMemoryTypeSystemMemory
;
2331 if ((ResourceHob
->ResourceAttribute
& MEMORY_ATTRIBUTE_MASK
) == INITIALIZED_MEMORY_ATTRIBUTES
) {
2332 GcdMemoryType
= EfiGcdMemoryTypeReserved
;
2334 if ((ResourceHob
->ResourceAttribute
& MEMORY_ATTRIBUTE_MASK
) == PRESENT_MEMORY_ATTRIBUTES
) {
2335 GcdMemoryType
= EfiGcdMemoryTypeReserved
;
2338 case EFI_RESOURCE_MEMORY_MAPPED_IO
:
2339 case EFI_RESOURCE_FIRMWARE_DEVICE
:
2340 GcdMemoryType
= EfiGcdMemoryTypeMemoryMappedIo
;
2342 case EFI_RESOURCE_MEMORY_MAPPED_IO_PORT
:
2343 case EFI_RESOURCE_MEMORY_RESERVED
:
2344 GcdMemoryType
= EfiGcdMemoryTypeReserved
;
2346 case EFI_RESOURCE_IO
:
2347 GcdIoType
= EfiGcdIoTypeIo
;
2349 case EFI_RESOURCE_IO_RESERVED
:
2350 GcdIoType
= EfiGcdIoTypeReserved
;
2354 if (GcdMemoryType
!= EfiGcdMemoryTypeNonExistent
) {
2357 // Convert the Resource HOB Attributes to an EFI Memory Capabilities mask
2359 Capabilities
= CoreConvertResourceDescriptorHobAttributesToCapabilities (
2361 ResourceHob
->ResourceAttribute
2364 Status
= CoreInternalAddMemorySpace (
2366 ResourceHob
->PhysicalStart
,
2367 ResourceHob
->ResourceLength
,
2372 if (GcdIoType
!= EfiGcdIoTypeNonExistent
) {
2373 Status
= CoreAddIoSpace (
2375 ResourceHob
->PhysicalStart
,
2376 ResourceHob
->ResourceLength
2383 // Allocate first memory region from the GCD by the DXE core
2385 Status
= CoreAllocateMemorySpace (
2386 EfiGcdAllocateAddress
,
2387 EfiGcdMemoryTypeSystemMemory
,
2391 gDxeCoreImageHandle
,
2396 // Walk the HOB list and allocate all memory space that is consumed by memory allocation HOBs,
2397 // and Firmware Volume HOBs. Also update the EFI Memory Map with the memory allocation HOBs.
2399 for (Hob
.Raw
= *HobStart
; !END_OF_HOB_LIST(Hob
); Hob
.Raw
= GET_NEXT_HOB(Hob
)) {
2400 if (GET_HOB_TYPE (Hob
) == EFI_HOB_TYPE_MEMORY_ALLOCATION
) {
2401 MemoryHob
= Hob
.MemoryAllocation
;
2402 BaseAddress
= MemoryHob
->AllocDescriptor
.MemoryBaseAddress
;
2403 Status
= CoreAllocateMemorySpace (
2404 EfiGcdAllocateAddress
,
2405 EfiGcdMemoryTypeSystemMemory
,
2407 MemoryHob
->AllocDescriptor
.MemoryLength
,
2409 gDxeCoreImageHandle
,
2412 if (!EFI_ERROR (Status
)) {
2413 Status
= CoreGetMemorySpaceDescriptor (MemoryHob
->AllocDescriptor
.MemoryBaseAddress
, &Descriptor
);
2414 if (!EFI_ERROR (Status
)) {
2415 CoreAddMemoryDescriptor (
2416 MemoryHob
->AllocDescriptor
.MemoryType
,
2417 MemoryHob
->AllocDescriptor
.MemoryBaseAddress
,
2418 RShiftU64 (MemoryHob
->AllocDescriptor
.MemoryLength
, EFI_PAGE_SHIFT
),
2419 Descriptor
.Capabilities
& (~EFI_MEMORY_RUNTIME
)
2425 if (GET_HOB_TYPE (Hob
) == EFI_HOB_TYPE_FV
) {
2426 FirmwareVolumeHob
= Hob
.FirmwareVolume
;
2427 BaseAddress
= FirmwareVolumeHob
->BaseAddress
;
2428 Status
= CoreAllocateMemorySpace (
2429 EfiGcdAllocateAddress
,
2430 EfiGcdMemoryTypeMemoryMappedIo
,
2432 FirmwareVolumeHob
->Length
,
2434 gDxeCoreImageHandle
,
2441 // Relocate HOB List to an allocated pool buffer.
2443 NewHobList
= CoreAllocateCopyPool (
2444 (UINTN
)PhitHob
->EfiFreeMemoryBottom
- (UINTN
)(*HobStart
),
2447 ASSERT (NewHobList
!= NULL
);
2449 *HobStart
= NewHobList
;
2452 // Add and allocate the remaining unallocated system memory to the memory services.
2454 Status
= CoreGetMemorySpaceMap (&NumberOfDescriptors
, &MemorySpaceMap
);
2455 for (Index
= 0; Index
< NumberOfDescriptors
; Index
++) {
2456 if (MemorySpaceMap
[Index
].GcdMemoryType
== EfiGcdMemoryTypeSystemMemory
) {
2457 if (MemorySpaceMap
[Index
].ImageHandle
== NULL
) {
2458 BaseAddress
= PageAlignAddress (MemorySpaceMap
[Index
].BaseAddress
);
2459 Length
= PageAlignLength (MemorySpaceMap
[Index
].BaseAddress
+ MemorySpaceMap
[Index
].Length
- BaseAddress
);
2460 CoreAddMemoryDescriptor (
2461 EfiConventionalMemory
,
2463 RShiftU64 (Length
, EFI_PAGE_SHIFT
),
2464 MemorySpaceMap
[Index
].Capabilities
& (~EFI_MEMORY_RUNTIME
)
2466 Status
= CoreAllocateMemorySpace (
2467 EfiGcdAllocateAddress
,
2468 EfiGcdMemoryTypeSystemMemory
,
2472 gDxeCoreImageHandle
,
2478 CoreFreePool (MemorySpaceMap
);