2 The file contains the GCD related services in the EFI Boot Services Table.
3 The GCD services are used to manage the memory and I/O regions that
4 are accessible to the CPU that is executing the DXE core.
6 Copyright (c) 2006 - 2008, Intel Corporation. <BR>
7 All rights reserved. This program and the accompanying materials
8 are licensed and made available under the terms and conditions of the BSD License
9 which accompanies this distribution. The full text of the license may be found at
10 http://opensource.org/licenses/bsd-license.php
12 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
13 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
19 #define MINIMUM_INITIAL_MEMORY_SIZE 0x10000
21 #define MEMORY_ATTRIBUTE_MASK (EFI_RESOURCE_ATTRIBUTE_PRESENT | \
22 EFI_RESOURCE_ATTRIBUTE_INITIALIZED | \
23 EFI_RESOURCE_ATTRIBUTE_TESTED | \
24 EFI_RESOURCE_ATTRIBUTE_READ_PROTECTED | \
25 EFI_RESOURCE_ATTRIBUTE_WRITE_PROTECTED | \
26 EFI_RESOURCE_ATTRIBUTE_EXECUTION_PROTECTED | \
27 EFI_RESOURCE_ATTRIBUTE_16_BIT_IO | \
28 EFI_RESOURCE_ATTRIBUTE_32_BIT_IO | \
29 EFI_RESOURCE_ATTRIBUTE_64_BIT_IO )
31 #define TESTED_MEMORY_ATTRIBUTES (EFI_RESOURCE_ATTRIBUTE_PRESENT | \
32 EFI_RESOURCE_ATTRIBUTE_INITIALIZED | \
33 EFI_RESOURCE_ATTRIBUTE_TESTED )
35 #define INITIALIZED_MEMORY_ATTRIBUTES (EFI_RESOURCE_ATTRIBUTE_PRESENT | \
36 EFI_RESOURCE_ATTRIBUTE_INITIALIZED )
38 #define PRESENT_MEMORY_ATTRIBUTES (EFI_RESOURCE_ATTRIBUTE_PRESENT)
40 #define INVALID_CPU_ARCH_ATTRIBUTES 0xffffffff
45 EFI_LOCK mGcdMemorySpaceLock
= EFI_INITIALIZE_LOCK_VARIABLE (TPL_NOTIFY
);
46 EFI_LOCK mGcdIoSpaceLock
= EFI_INITIALIZE_LOCK_VARIABLE (TPL_NOTIFY
);
47 LIST_ENTRY mGcdMemorySpaceMap
= INITIALIZE_LIST_HEAD_VARIABLE (mGcdMemorySpaceMap
);
48 LIST_ENTRY mGcdIoSpaceMap
= INITIALIZE_LIST_HEAD_VARIABLE (mGcdIoSpaceMap
);
50 EFI_GCD_MAP_ENTRY mGcdMemorySpaceMapEntryTemplate
= {
51 EFI_GCD_MAP_SIGNATURE
,
60 EfiGcdMemoryTypeNonExistent
,
66 EFI_GCD_MAP_ENTRY mGcdIoSpaceMapEntryTemplate
= {
67 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
},
99 Acquire memory lock on mGcdMemorySpaceLock.
103 CoreAcquireGcdMemoryLock (
107 CoreAcquireLock (&mGcdMemorySpaceLock
);
113 Release memory lock on mGcdMemorySpaceLock.
117 CoreReleaseGcdMemoryLock (
121 CoreReleaseLock (&mGcdMemorySpaceLock
);
127 Acquire memory lock on mGcdIoSpaceLock.
131 CoreAcquireGcdIoLock (
135 CoreAcquireLock (&mGcdIoSpaceLock
);
140 Release memory lock on mGcdIoSpaceLock.
144 CoreReleaseGcdIoLock (
148 CoreReleaseLock (&mGcdIoSpaceLock
);
154 // GCD Initialization Worker Functions
157 Aligns a value to the specified boundary.
159 @param Value 64 bit value to align
160 @param Alignment Log base 2 of the boundary to align Value to
161 @param RoundUp TRUE if Value is to be rounded up to the nearest
162 aligned boundary. FALSE is Value is to be
163 rounded down to the nearest aligned boundary.
165 @return A 64 bit value is the aligned to the value nearest Value with an alignment by Alignment.
175 UINT64 AlignmentMask
;
177 AlignmentMask
= LShiftU64 (1, Alignment
) - 1;
179 Value
+= AlignmentMask
;
181 return Value
& (~AlignmentMask
);
186 Aligns address to the page boundary.
188 @param Value 64 bit address to align
190 @return A 64 bit value is the aligned to the value nearest Value with an alignment by Alignment.
198 return AlignValue (Value
, EFI_PAGE_SHIFT
, TRUE
);
203 Aligns length to the page boundary.
205 @param Value 64 bit length to align
207 @return A 64 bit value is the aligned to the value nearest Value with an alignment by Alignment.
215 return AlignValue (Value
, EFI_PAGE_SHIFT
, FALSE
);
219 // GCD Memory Space Worker Functions
223 Allocate pool for two entries.
225 @param TopEntry An entry of GCD map
226 @param BottomEntry An entry of GCD map
228 @retval EFI_OUT_OF_RESOURCES No enough buffer to be allocated.
229 @retval EFI_SUCCESS Both entries successfully allocated.
233 CoreAllocateGcdMapEntry (
234 IN OUT EFI_GCD_MAP_ENTRY
**TopEntry
,
235 IN OUT EFI_GCD_MAP_ENTRY
**BottomEntry
238 *TopEntry
= AllocateZeroPool (sizeof (EFI_GCD_MAP_ENTRY
));
239 if (*TopEntry
== NULL
) {
240 return EFI_OUT_OF_RESOURCES
;
243 *BottomEntry
= AllocateZeroPool (sizeof (EFI_GCD_MAP_ENTRY
));
244 if (*BottomEntry
== NULL
) {
245 CoreFreePool (*TopEntry
);
246 return EFI_OUT_OF_RESOURCES
;
254 Internal function. Inserts a new descriptor into a sorted list
256 @param Link The linked list to insert the range BaseAddress
258 @param Entry A pointer to the entry that is inserted
259 @param BaseAddress The base address of the new range
260 @param Length The length of the new range in bytes
261 @param TopEntry Top pad entry to insert if needed.
262 @param BottomEntry Bottom pad entry to insert if needed.
264 @retval EFI_SUCCESS The new range was inserted into the linked list
268 CoreInsertGcdMapEntry (
270 IN EFI_GCD_MAP_ENTRY
*Entry
,
271 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
273 IN EFI_GCD_MAP_ENTRY
*TopEntry
,
274 IN EFI_GCD_MAP_ENTRY
*BottomEntry
277 ASSERT (Length
!= 0);
278 ASSERT (TopEntry
->Signature
== 0);
279 ASSERT (BottomEntry
->Signature
== 0);
281 if (BaseAddress
> Entry
->BaseAddress
) {
282 CopyMem (BottomEntry
, Entry
, sizeof (EFI_GCD_MAP_ENTRY
));
283 Entry
->BaseAddress
= BaseAddress
;
284 BottomEntry
->EndAddress
= BaseAddress
- 1;
285 InsertTailList (Link
, &BottomEntry
->Link
);
288 if ((BaseAddress
+ Length
- 1) < Entry
->EndAddress
) {
289 CopyMem (TopEntry
, Entry
, sizeof (EFI_GCD_MAP_ENTRY
));
290 TopEntry
->BaseAddress
= BaseAddress
+ Length
;
291 Entry
->EndAddress
= BaseAddress
+ Length
- 1;
292 InsertHeadList (Link
, &TopEntry
->Link
);
300 Merge the Gcd region specified by Link and its adjacent entry.
302 @param Link Specify the entry to be merged (with its
304 @param Forward Direction (forward or backward).
307 @retval EFI_SUCCESS Successfully returned.
308 @retval EFI_UNSUPPORTED These adjacent regions could not merge.
312 CoreMergeGcdMapEntry (
318 LIST_ENTRY
*AdjacentLink
;
319 EFI_GCD_MAP_ENTRY
*Entry
;
320 EFI_GCD_MAP_ENTRY
*AdjacentEntry
;
323 // Get adjacent entry
326 AdjacentLink
= Link
->ForwardLink
;
328 AdjacentLink
= Link
->BackLink
;
332 // If AdjacentLink is the head of the list, then no merge can be performed
334 if (AdjacentLink
== Map
) {
338 Entry
= CR (Link
, EFI_GCD_MAP_ENTRY
, Link
, EFI_GCD_MAP_SIGNATURE
);
339 AdjacentEntry
= CR (AdjacentLink
, EFI_GCD_MAP_ENTRY
, Link
, EFI_GCD_MAP_SIGNATURE
);
341 if (Entry
->Capabilities
!= AdjacentEntry
->Capabilities
) {
342 return EFI_UNSUPPORTED
;
344 if (Entry
->Attributes
!= AdjacentEntry
->Attributes
) {
345 return EFI_UNSUPPORTED
;
347 if (Entry
->GcdMemoryType
!= AdjacentEntry
->GcdMemoryType
) {
348 return EFI_UNSUPPORTED
;
350 if (Entry
->GcdIoType
!= AdjacentEntry
->GcdIoType
) {
351 return EFI_UNSUPPORTED
;
353 if (Entry
->ImageHandle
!= AdjacentEntry
->ImageHandle
) {
354 return EFI_UNSUPPORTED
;
356 if (Entry
->DeviceHandle
!= AdjacentEntry
->DeviceHandle
) {
357 return EFI_UNSUPPORTED
;
361 Entry
->EndAddress
= AdjacentEntry
->EndAddress
;
363 Entry
->BaseAddress
= AdjacentEntry
->BaseAddress
;
365 RemoveEntryList (AdjacentLink
);
366 CoreFreePool (AdjacentEntry
);
373 Merge adjacent entries on total chain.
375 @param TopEntry Top entry of GCD map.
376 @param BottomEntry Bottom entry of GCD map.
377 @param StartLink Start link of the list for this loop.
378 @param EndLink End link of the list for this loop.
381 @retval EFI_SUCCESS GCD map successfully cleaned up.
385 CoreCleanupGcdMapEntry (
386 IN EFI_GCD_MAP_ENTRY
*TopEntry
,
387 IN EFI_GCD_MAP_ENTRY
*BottomEntry
,
388 IN LIST_ENTRY
*StartLink
,
389 IN LIST_ENTRY
*EndLink
,
395 if (TopEntry
->Signature
== 0) {
396 CoreFreePool (TopEntry
);
398 if (BottomEntry
->Signature
== 0) {
399 CoreFreePool (BottomEntry
);
403 while (Link
!= EndLink
->ForwardLink
) {
404 CoreMergeGcdMapEntry (Link
, FALSE
, Map
);
405 Link
= Link
->ForwardLink
;
407 CoreMergeGcdMapEntry (EndLink
, TRUE
, Map
);
414 Search a segment of memory space in GCD map. The result is a range of GCD entry list.
416 @param BaseAddress The start address of the segment.
417 @param Length The length of the segment.
418 @param StartLink The first GCD entry involves this segment of
420 @param EndLink The first GCD entry involves this segment of
422 @param Map Points to the start entry to search.
424 @retval EFI_SUCCESS Successfully found the entry.
425 @retval EFI_NOT_FOUND Not found.
429 CoreSearchGcdMapEntry (
430 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
432 OUT LIST_ENTRY
**StartLink
,
433 OUT LIST_ENTRY
**EndLink
,
438 EFI_GCD_MAP_ENTRY
*Entry
;
440 ASSERT (Length
!= 0);
445 Link
= Map
->ForwardLink
;
446 while (Link
!= Map
) {
447 Entry
= CR (Link
, EFI_GCD_MAP_ENTRY
, Link
, EFI_GCD_MAP_SIGNATURE
);
448 if (BaseAddress
>= Entry
->BaseAddress
&& BaseAddress
<= Entry
->EndAddress
) {
451 if (*StartLink
!= NULL
) {
452 if ((BaseAddress
+ Length
- 1) >= Entry
->BaseAddress
&&
453 (BaseAddress
+ Length
- 1) <= Entry
->EndAddress
) {
458 Link
= Link
->ForwardLink
;
461 return EFI_NOT_FOUND
;
466 Count the amount of GCD map entries.
468 @param Map Points to the start entry to do the count loop.
474 CoreCountGcdMapEntry (
482 Link
= Map
->ForwardLink
;
483 while (Link
!= Map
) {
485 Link
= Link
->ForwardLink
;
494 Return the memory attribute specified by Attributes
496 @param Attributes A num with some attribute bits on.
498 @return The enum value of memory attribute.
502 ConverToCpuArchAttributes (
506 if ( (Attributes
& EFI_MEMORY_UC
) == EFI_MEMORY_UC
) {
507 return EFI_MEMORY_UC
;
510 if ( (Attributes
& EFI_MEMORY_WC
) == EFI_MEMORY_WC
) {
511 return EFI_MEMORY_WC
;
514 if ( (Attributes
& EFI_MEMORY_WT
) == EFI_MEMORY_WT
) {
515 return EFI_MEMORY_WT
;
518 if ( (Attributes
& EFI_MEMORY_WB
) == EFI_MEMORY_WB
) {
519 return EFI_MEMORY_WB
;
522 if ( (Attributes
& EFI_MEMORY_WP
) == EFI_MEMORY_WP
) {
523 return EFI_MEMORY_WP
;
526 return INVALID_CPU_ARCH_ATTRIBUTES
;
532 Do operation on a segment of memory space specified (add, free, remove, change attribute ...).
534 @param Operation The type of the operation
535 @param GcdMemoryType Additional information for the operation
536 @param GcdIoType Additional information for the operation
537 @param BaseAddress Start address of the segment
538 @param Length length of the segment
539 @param Capabilities The alterable attributes of a newly added entry
540 @param Attributes The attributes needs to be set
542 @retval EFI_INVALID_PARAMETER Length is 0 or address (length) not aligned when
544 @retval EFI_SUCCESS Action successfully done.
545 @retval EFI_UNSUPPORTED Could not find the proper descriptor on this
546 segment or set an upsupported attribute.
547 @retval EFI_ACCESS_DENIED Operate on an space non-exist or is used for an
549 @retval EFI_NOT_FOUND Free a non-using space or remove a non-exist
551 @retval EFI_OUT_OF_RESOURCES No buffer could be allocated.
557 IN EFI_GCD_MEMORY_TYPE GcdMemoryType
,
558 IN EFI_GCD_IO_TYPE GcdIoType
,
559 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
561 IN UINT64 Capabilities
,
568 EFI_GCD_MAP_ENTRY
*Entry
;
569 EFI_GCD_MAP_ENTRY
*TopEntry
;
570 EFI_GCD_MAP_ENTRY
*BottomEntry
;
571 LIST_ENTRY
*StartLink
;
574 EFI_CPU_ARCH_PROTOCOL
*CpuArch
;
575 UINT64 CpuArchAttributes
;
578 return EFI_INVALID_PARAMETER
;
582 if ((Operation
& GCD_MEMORY_SPACE_OPERATION
) != 0) {
583 CoreAcquireGcdMemoryLock ();
584 Map
= &mGcdMemorySpaceMap
;
586 if ((Operation
& GCD_IO_SPACE_OPERATION
) != 0) {
587 CoreAcquireGcdIoLock ();
588 Map
= &mGcdIoSpaceMap
;
592 // Search for the list of descriptors that cover the range BaseAddress to BaseAddress+Length
594 Status
= CoreSearchGcdMapEntry (BaseAddress
, Length
, &StartLink
, &EndLink
, Map
);
595 if (EFI_ERROR (Status
)) {
596 Status
= EFI_UNSUPPORTED
;
602 // Verify that the list of descriptors are unallocated non-existent memory.
605 while (Link
!= EndLink
->ForwardLink
) {
606 Entry
= CR (Link
, EFI_GCD_MAP_ENTRY
, Link
, EFI_GCD_MAP_SIGNATURE
);
611 case GCD_ADD_MEMORY_OPERATION
:
612 if (Entry
->GcdMemoryType
!= EfiGcdMemoryTypeNonExistent
||
613 Entry
->ImageHandle
!= NULL
) {
614 Status
= EFI_ACCESS_DENIED
;
618 case GCD_ADD_IO_OPERATION
:
619 if (Entry
->GcdIoType
!= EfiGcdIoTypeNonExistent
||
620 Entry
->ImageHandle
!= NULL
) {
621 Status
= EFI_ACCESS_DENIED
;
628 case GCD_FREE_MEMORY_OPERATION
:
629 case GCD_FREE_IO_OPERATION
:
630 if (Entry
->ImageHandle
== NULL
) {
631 Status
= EFI_NOT_FOUND
;
638 case GCD_REMOVE_MEMORY_OPERATION
:
639 if (Entry
->GcdMemoryType
== EfiGcdMemoryTypeNonExistent
) {
640 Status
= EFI_NOT_FOUND
;
643 if (Entry
->ImageHandle
!= NULL
) {
644 Status
= EFI_ACCESS_DENIED
;
648 case GCD_REMOVE_IO_OPERATION
:
649 if (Entry
->GcdIoType
== EfiGcdIoTypeNonExistent
) {
650 Status
= EFI_NOT_FOUND
;
653 if (Entry
->ImageHandle
!= NULL
) {
654 Status
= EFI_ACCESS_DENIED
;
659 // Set attribute operations
661 case GCD_SET_ATTRIBUTES_MEMORY_OPERATION
:
662 if ((Attributes
& EFI_MEMORY_RUNTIME
) != 0) {
663 if ((BaseAddress
& EFI_PAGE_MASK
) != 0 || (Length
& EFI_PAGE_MASK
) != 0) {
664 Status
= EFI_INVALID_PARAMETER
;
668 if ((Entry
->Capabilities
& Attributes
) != Attributes
) {
669 Status
= EFI_UNSUPPORTED
;
674 Link
= Link
->ForwardLink
;
678 // Allocate work space to perform this operation
680 Status
= CoreAllocateGcdMapEntry (&TopEntry
, &BottomEntry
);
681 if (EFI_ERROR (Status
)) {
682 Status
= EFI_OUT_OF_RESOURCES
;
686 if (Operation
== GCD_SET_ATTRIBUTES_MEMORY_OPERATION
) {
688 // Call CPU Arch Protocol to attempt to set attributes on the range
690 CpuArchAttributes
= ConverToCpuArchAttributes (Attributes
);
691 if ( CpuArchAttributes
!= INVALID_CPU_ARCH_ATTRIBUTES
) {
692 Status
= CoreLocateProtocol (&gEfiCpuArchProtocolGuid
, NULL
, (VOID
**)&CpuArch
);
693 if (EFI_ERROR (Status
)) {
694 Status
= EFI_ACCESS_DENIED
;
698 Status
= CpuArch
->SetMemoryAttributes (
704 if (EFI_ERROR (Status
)) {
712 // Convert/Insert the list of descriptors from StartLink to EndLink
715 while (Link
!= EndLink
->ForwardLink
) {
716 Entry
= CR (Link
, EFI_GCD_MAP_ENTRY
, Link
, EFI_GCD_MAP_SIGNATURE
);
717 CoreInsertGcdMapEntry (Link
, Entry
, BaseAddress
, Length
, TopEntry
, BottomEntry
);
722 case GCD_ADD_MEMORY_OPERATION
:
723 Entry
->GcdMemoryType
= GcdMemoryType
;
724 if (GcdMemoryType
== EfiGcdMemoryTypeMemoryMappedIo
) {
725 Entry
->Capabilities
= Capabilities
| EFI_MEMORY_RUNTIME
| EFI_MEMORY_PORT_IO
;
727 Entry
->Capabilities
= Capabilities
| EFI_MEMORY_RUNTIME
;
730 case GCD_ADD_IO_OPERATION
:
731 Entry
->GcdIoType
= GcdIoType
;
736 case GCD_FREE_MEMORY_OPERATION
:
737 case GCD_FREE_IO_OPERATION
:
738 Entry
->ImageHandle
= NULL
;
739 Entry
->DeviceHandle
= NULL
;
744 case GCD_REMOVE_MEMORY_OPERATION
:
745 Entry
->GcdMemoryType
= EfiGcdMemoryTypeNonExistent
;
746 Entry
->Capabilities
= 0;
748 case GCD_REMOVE_IO_OPERATION
:
749 Entry
->GcdIoType
= EfiGcdIoTypeNonExistent
;
752 // Set attribute operations
754 case GCD_SET_ATTRIBUTES_MEMORY_OPERATION
:
755 Entry
->Attributes
= Attributes
;
758 Link
= Link
->ForwardLink
;
764 Status
= CoreCleanupGcdMapEntry (TopEntry
, BottomEntry
, StartLink
, EndLink
, Map
);
767 if ((Operation
& GCD_MEMORY_SPACE_OPERATION
) != 0) {
768 CoreReleaseGcdMemoryLock ();
770 if ((Operation
& GCD_IO_SPACE_OPERATION
) != 0) {
771 CoreReleaseGcdIoLock ();
779 Check whether an entry could be used to allocate space.
781 @param Operation Allocate memory or IO
782 @param Entry The entry to be tested
783 @param GcdMemoryType The desired memory type
784 @param GcdIoType The desired IO type
786 @retval EFI_NOT_FOUND The memory type does not match or there's an
787 image handle on the entry.
788 @retval EFI_UNSUPPORTED The operation unsupported.
789 @retval EFI_SUCCESS It's ok for this entry to be used to allocate
794 CoreAllocateSpaceCheckEntry (
796 IN EFI_GCD_MAP_ENTRY
*Entry
,
797 IN EFI_GCD_MEMORY_TYPE GcdMemoryType
,
798 IN EFI_GCD_IO_TYPE GcdIoType
801 if (Entry
->ImageHandle
!= NULL
) {
802 return EFI_NOT_FOUND
;
805 case GCD_ALLOCATE_MEMORY_OPERATION
:
806 if (Entry
->GcdMemoryType
!= GcdMemoryType
) {
807 return EFI_NOT_FOUND
;
810 case GCD_ALLOCATE_IO_OPERATION
:
811 if (Entry
->GcdIoType
!= GcdIoType
) {
812 return EFI_NOT_FOUND
;
816 return EFI_UNSUPPORTED
;
823 Allocate space on specified address and length.
825 @param Operation The type of operation (memory or IO)
826 @param GcdAllocateType The type of allocate operation
827 @param GcdMemoryType The desired memory type
828 @param GcdIoType The desired IO type
829 @param Alignment Align with 2^Alignment
830 @param Length Length to allocate
831 @param BaseAddress Base address to allocate
832 @param ImageHandle The image handle consume the allocated space.
833 @param DeviceHandle The device handle consume the allocated space.
835 @retval EFI_INVALID_PARAMETER Invalid parameter.
836 @retval EFI_NOT_FOUND No descriptor for the desired space exists.
837 @retval EFI_SUCCESS Space successfully allocated.
843 IN EFI_GCD_ALLOCATE_TYPE GcdAllocateType
,
844 IN EFI_GCD_MEMORY_TYPE GcdMemoryType
,
845 IN EFI_GCD_IO_TYPE GcdIoType
,
848 IN OUT EFI_PHYSICAL_ADDRESS
*BaseAddress
,
849 IN EFI_HANDLE ImageHandle
,
850 IN EFI_HANDLE DeviceHandle OPTIONAL
854 EFI_PHYSICAL_ADDRESS AlignmentMask
;
855 EFI_PHYSICAL_ADDRESS MaxAddress
;
859 EFI_GCD_MAP_ENTRY
*Entry
;
860 EFI_GCD_MAP_ENTRY
*TopEntry
;
861 EFI_GCD_MAP_ENTRY
*BottomEntry
;
862 LIST_ENTRY
*StartLink
;
867 // Make sure parameters are valid
869 if (GcdAllocateType
< 0 || GcdAllocateType
>= EfiGcdMaxAllocateType
) {
870 return EFI_INVALID_PARAMETER
;
872 if (GcdMemoryType
< 0 || GcdMemoryType
>= EfiGcdMemoryTypeMaximum
) {
873 return EFI_INVALID_PARAMETER
;
875 if (GcdIoType
< 0 || GcdIoType
>= EfiGcdIoTypeMaximum
) {
876 return EFI_INVALID_PARAMETER
;
878 if (BaseAddress
== NULL
) {
879 return EFI_INVALID_PARAMETER
;
881 if (ImageHandle
== NULL
) {
882 return EFI_INVALID_PARAMETER
;
884 if (Alignment
>= 64) {
885 return EFI_NOT_FOUND
;
888 return EFI_INVALID_PARAMETER
;
892 if ((Operation
& GCD_MEMORY_SPACE_OPERATION
) != 0) {
893 CoreAcquireGcdMemoryLock ();
894 Map
= &mGcdMemorySpaceMap
;
896 if ((Operation
& GCD_IO_SPACE_OPERATION
) != 0) {
897 CoreAcquireGcdIoLock ();
898 Map
= &mGcdIoSpaceMap
;
905 // Compute alignment bit mask
907 AlignmentMask
= LShiftU64 (1, Alignment
) - 1;
909 if (GcdAllocateType
== EfiGcdAllocateAddress
) {
911 // Verify that the BaseAddress passed in is aligned correctly
913 if ((*BaseAddress
& AlignmentMask
) != 0) {
914 Status
= EFI_NOT_FOUND
;
919 // Search for the list of descriptors that cover the range BaseAddress to BaseAddress+Length
921 Status
= CoreSearchGcdMapEntry (*BaseAddress
, Length
, &StartLink
, &EndLink
, Map
);
922 if (EFI_ERROR (Status
)) {
923 Status
= EFI_NOT_FOUND
;
928 // Verify that the list of descriptors are unallocated memory matching GcdMemoryType.
931 while (Link
!= EndLink
->ForwardLink
) {
932 Entry
= CR (Link
, EFI_GCD_MAP_ENTRY
, Link
, EFI_GCD_MAP_SIGNATURE
);
933 Link
= Link
->ForwardLink
;
934 Status
= CoreAllocateSpaceCheckEntry (Operation
, Entry
, GcdMemoryType
, GcdIoType
);
935 if (EFI_ERROR (Status
)) {
942 Entry
= CR (Map
->BackLink
, EFI_GCD_MAP_ENTRY
, Link
, EFI_GCD_MAP_SIGNATURE
);
945 // Compute the maximum address to use in the search algorithm
947 if (GcdAllocateType
== EfiGcdAllocateMaxAddressSearchBottomUp
||
948 GcdAllocateType
== EfiGcdAllocateMaxAddressSearchTopDown
) {
949 MaxAddress
= *BaseAddress
;
951 MaxAddress
= Entry
->EndAddress
;
955 // Verify that the list of descriptors are unallocated memory matching GcdMemoryType.
957 if (GcdAllocateType
== EfiGcdAllocateMaxAddressSearchTopDown
||
958 GcdAllocateType
== EfiGcdAllocateAnySearchTopDown
) {
959 Link
= Map
->BackLink
;
961 Link
= Map
->ForwardLink
;
963 while (Link
!= Map
) {
964 Entry
= CR (Link
, EFI_GCD_MAP_ENTRY
, Link
, EFI_GCD_MAP_SIGNATURE
);
966 if (GcdAllocateType
== EfiGcdAllocateMaxAddressSearchTopDown
||
967 GcdAllocateType
== EfiGcdAllocateAnySearchTopDown
) {
968 Link
= Link
->BackLink
;
970 Link
= Link
->ForwardLink
;
973 Status
= CoreAllocateSpaceCheckEntry (Operation
, Entry
, GcdMemoryType
, GcdIoType
);
974 if (EFI_ERROR (Status
)) {
978 if (GcdAllocateType
== EfiGcdAllocateMaxAddressSearchTopDown
||
979 GcdAllocateType
== EfiGcdAllocateAnySearchTopDown
) {
980 if ((Entry
->BaseAddress
+ Length
) > MaxAddress
) {
983 if (Length
> (Entry
->EndAddress
+ 1)) {
984 Status
= EFI_NOT_FOUND
;
987 if (Entry
->EndAddress
> MaxAddress
) {
988 *BaseAddress
= MaxAddress
;
990 *BaseAddress
= Entry
->EndAddress
;
992 *BaseAddress
= (*BaseAddress
+ 1 - Length
) & (~AlignmentMask
);
994 *BaseAddress
= (Entry
->BaseAddress
+ AlignmentMask
) & (~AlignmentMask
);
995 if ((*BaseAddress
+ Length
- 1) > MaxAddress
) {
996 Status
= EFI_NOT_FOUND
;
1002 // Search for the list of descriptors that cover the range BaseAddress to BaseAddress+Length
1004 Status
= CoreSearchGcdMapEntry (*BaseAddress
, Length
, &StartLink
, &EndLink
, Map
);
1005 if (EFI_ERROR (Status
)) {
1006 Status
= EFI_NOT_FOUND
;
1012 // Verify that the list of descriptors are unallocated memory matching GcdMemoryType.
1015 SubLink
= StartLink
;
1016 while (SubLink
!= EndLink
->ForwardLink
) {
1017 Entry
= CR (SubLink
, EFI_GCD_MAP_ENTRY
, Link
, EFI_GCD_MAP_SIGNATURE
);
1018 Status
= CoreAllocateSpaceCheckEntry (Operation
, Entry
, GcdMemoryType
, GcdIoType
);
1019 if (EFI_ERROR (Status
)) {
1024 SubLink
= SubLink
->ForwardLink
;
1032 Status
= EFI_NOT_FOUND
;
1037 // Allocate work space to perform this operation
1039 Status
= CoreAllocateGcdMapEntry (&TopEntry
, &BottomEntry
);
1040 if (EFI_ERROR (Status
)) {
1041 Status
= EFI_OUT_OF_RESOURCES
;
1046 // Convert/Insert the list of descriptors from StartLink to EndLink
1049 while (Link
!= EndLink
->ForwardLink
) {
1050 Entry
= CR (Link
, EFI_GCD_MAP_ENTRY
, Link
, EFI_GCD_MAP_SIGNATURE
);
1051 CoreInsertGcdMapEntry (Link
, Entry
, *BaseAddress
, Length
, TopEntry
, BottomEntry
);
1052 Entry
->ImageHandle
= ImageHandle
;
1053 Entry
->DeviceHandle
= DeviceHandle
;
1054 Link
= Link
->ForwardLink
;
1060 Status
= CoreCleanupGcdMapEntry (TopEntry
, BottomEntry
, StartLink
, EndLink
, Map
);
1063 if ((Operation
& GCD_MEMORY_SPACE_OPERATION
) != 0) {
1064 CoreReleaseGcdMemoryLock ();
1066 if ((Operation
& GCD_IO_SPACE_OPERATION
) !=0) {
1067 CoreReleaseGcdIoLock ();
1075 Add a segment of memory to GCD map.
1077 @param GcdMemoryType Memory type of the segment.
1078 @param BaseAddress Base address of the segment.
1079 @param Length Length of the segment.
1080 @param Capabilities alterable attributes of the segment.
1082 @retval EFI_INVALID_PARAMETER Invalid parameters.
1083 @retval EFI_SUCCESS Successfully add a segment of memory space.
1087 CoreInternalAddMemorySpace (
1088 IN EFI_GCD_MEMORY_TYPE GcdMemoryType
,
1089 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
1091 IN UINT64 Capabilities
1095 // Make sure parameters are valid
1097 if (GcdMemoryType
<= EfiGcdMemoryTypeNonExistent
|| GcdMemoryType
>= EfiGcdMemoryTypeMaximum
) {
1098 return EFI_INVALID_PARAMETER
;
1101 return CoreConvertSpace (GCD_ADD_MEMORY_OPERATION
, GcdMemoryType
, (EFI_GCD_IO_TYPE
) 0, BaseAddress
, Length
, Capabilities
, 0);
1105 // GCD Core Services
1109 Allocates nonexistent memory, reserved memory, system memory, or memorymapped
1110 I/O resources from the global coherency domain of the processor.
1112 @param GcdAllocateType The type of allocate operation
1113 @param GcdMemoryType The desired memory type
1114 @param Alignment Align with 2^Alignment
1115 @param Length Length to allocate
1116 @param BaseAddress Base address to allocate
1117 @param ImageHandle The image handle consume the allocated space.
1118 @param DeviceHandle The device handle consume the allocated space.
1120 @retval EFI_INVALID_PARAMETER Invalid parameter.
1121 @retval EFI_NOT_FOUND No descriptor contains the desired space.
1122 @retval EFI_SUCCESS Memory space successfully allocated.
1127 CoreAllocateMemorySpace (
1128 IN EFI_GCD_ALLOCATE_TYPE GcdAllocateType
,
1129 IN EFI_GCD_MEMORY_TYPE GcdMemoryType
,
1132 IN OUT EFI_PHYSICAL_ADDRESS
*BaseAddress
,
1133 IN EFI_HANDLE ImageHandle
,
1134 IN EFI_HANDLE DeviceHandle OPTIONAL
1137 return CoreAllocateSpace (
1138 GCD_ALLOCATE_MEMORY_OPERATION
,
1141 (EFI_GCD_IO_TYPE
) 0,
1152 Adds reserved memory, system memory, or memory-mapped I/O resources to the
1153 global coherency domain of the processor.
1155 @param GcdMemoryType Memory type of the memory space.
1156 @param BaseAddress Base address of the memory space.
1157 @param Length Length of the memory space.
1158 @param Capabilities alterable attributes of the memory space.
1160 @retval EFI_SUCCESS Merged this memory space into GCD map.
1165 CoreAddMemorySpace (
1166 IN EFI_GCD_MEMORY_TYPE GcdMemoryType
,
1167 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
1169 IN UINT64 Capabilities
1173 EFI_PHYSICAL_ADDRESS PageBaseAddress
;
1176 Status
= CoreInternalAddMemorySpace (GcdMemoryType
, BaseAddress
, Length
, Capabilities
);
1178 if (!EFI_ERROR (Status
) && GcdMemoryType
== EfiGcdMemoryTypeSystemMemory
) {
1180 PageBaseAddress
= PageAlignLength (BaseAddress
);
1181 PageLength
= PageAlignLength (BaseAddress
+ Length
- PageBaseAddress
);
1183 Status
= CoreAllocateMemorySpace (
1184 EfiGcdAllocateAddress
,
1189 gDxeCoreImageHandle
,
1193 if (!EFI_ERROR (Status
)) {
1194 CoreAddMemoryDescriptor (
1195 EfiConventionalMemory
,
1197 RShiftU64 (PageLength
, EFI_PAGE_SHIFT
),
1201 for (; PageLength
!= 0; PageLength
-= EFI_PAGE_SIZE
, PageBaseAddress
+= EFI_PAGE_SIZE
) {
1202 Status
= CoreAllocateMemorySpace (
1203 EfiGcdAllocateAddress
,
1208 gDxeCoreImageHandle
,
1212 if (!EFI_ERROR (Status
)) {
1213 CoreAddMemoryDescriptor (
1214 EfiConventionalMemory
,
1228 Frees nonexistent memory, reserved memory, system memory, or memory-mapped
1229 I/O resources from the global coherency domain of the processor.
1231 @param BaseAddress Base address of the memory space.
1232 @param Length Length of the memory space.
1234 @retval EFI_SUCCESS Space successfully freed.
1239 CoreFreeMemorySpace (
1240 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
1244 return CoreConvertSpace (GCD_FREE_MEMORY_OPERATION
, (EFI_GCD_MEMORY_TYPE
) 0, (EFI_GCD_IO_TYPE
) 0, BaseAddress
, Length
, 0, 0);
1249 Removes reserved memory, system memory, or memory-mapped I/O resources from
1250 the global coherency domain of the processor.
1252 @param BaseAddress Base address of the memory space.
1253 @param Length Length of the memory space.
1255 @retval EFI_SUCCESS Successfully remove a segment of memory space.
1260 CoreRemoveMemorySpace (
1261 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
1265 return CoreConvertSpace (GCD_REMOVE_MEMORY_OPERATION
, (EFI_GCD_MEMORY_TYPE
) 0, (EFI_GCD_IO_TYPE
) 0, BaseAddress
, Length
, 0, 0);
1270 Build a memory descriptor according to an entry.
1272 @param Descriptor The descriptor to be built
1273 @param Entry According to this entry
1277 BuildMemoryDescriptor (
1278 IN OUT EFI_GCD_MEMORY_SPACE_DESCRIPTOR
*Descriptor
,
1279 IN EFI_GCD_MAP_ENTRY
*Entry
1282 Descriptor
->BaseAddress
= Entry
->BaseAddress
;
1283 Descriptor
->Length
= Entry
->EndAddress
- Entry
->BaseAddress
+ 1;
1284 Descriptor
->Capabilities
= Entry
->Capabilities
;
1285 Descriptor
->Attributes
= Entry
->Attributes
;
1286 Descriptor
->GcdMemoryType
= Entry
->GcdMemoryType
;
1287 Descriptor
->ImageHandle
= Entry
->ImageHandle
;
1288 Descriptor
->DeviceHandle
= Entry
->DeviceHandle
;
1293 Retrieves the descriptor for a memory region containing a specified address.
1295 @param BaseAddress Specified start address
1296 @param Descriptor Specified length
1298 @retval EFI_INVALID_PARAMETER Invalid parameter
1299 @retval EFI_SUCCESS Successfully get memory space descriptor.
1304 CoreGetMemorySpaceDescriptor (
1305 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
1306 OUT EFI_GCD_MEMORY_SPACE_DESCRIPTOR
*Descriptor
1310 LIST_ENTRY
*StartLink
;
1311 LIST_ENTRY
*EndLink
;
1312 EFI_GCD_MAP_ENTRY
*Entry
;
1315 // Make sure parameters are valid
1317 if (Descriptor
== NULL
) {
1318 return EFI_INVALID_PARAMETER
;
1321 CoreAcquireGcdMemoryLock ();
1324 // Search for the list of descriptors that contain BaseAddress
1326 Status
= CoreSearchGcdMapEntry (BaseAddress
, 1, &StartLink
, &EndLink
, &mGcdMemorySpaceMap
);
1327 if (EFI_ERROR (Status
)) {
1328 Status
= EFI_NOT_FOUND
;
1331 // Copy the contents of the found descriptor into Descriptor
1333 Entry
= CR (StartLink
, EFI_GCD_MAP_ENTRY
, Link
, EFI_GCD_MAP_SIGNATURE
);
1334 BuildMemoryDescriptor (Descriptor
, Entry
);
1337 CoreReleaseGcdMemoryLock ();
1344 Modifies the attributes for a memory region in the global coherency domain of the
1347 @param BaseAddress Specified start address
1348 @param Length Specified length
1349 @param Attributes Specified attributes
1351 @retval EFI_SUCCESS Successfully set attribute of a segment of
1357 CoreSetMemorySpaceAttributes (
1358 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
1360 IN UINT64 Attributes
1363 return CoreConvertSpace (GCD_SET_ATTRIBUTES_MEMORY_OPERATION
, (EFI_GCD_MEMORY_TYPE
) 0, (EFI_GCD_IO_TYPE
) 0, BaseAddress
, Length
, 0, Attributes
);
1368 Returns a map of the memory resources in the global coherency domain of the
1371 @param NumberOfDescriptors Number of descriptors.
1372 @param MemorySpaceMap Descriptor array
1374 @retval EFI_INVALID_PARAMETER Invalid parameter
1375 @retval EFI_OUT_OF_RESOURCES No enough buffer to allocate
1376 @retval EFI_SUCCESS Successfully get memory space map.
1381 CoreGetMemorySpaceMap (
1382 OUT UINTN
*NumberOfDescriptors
,
1383 OUT EFI_GCD_MEMORY_SPACE_DESCRIPTOR
**MemorySpaceMap
1388 EFI_GCD_MAP_ENTRY
*Entry
;
1389 EFI_GCD_MEMORY_SPACE_DESCRIPTOR
*Descriptor
;
1392 // Make sure parameters are valid
1394 if (NumberOfDescriptors
== NULL
) {
1395 return EFI_INVALID_PARAMETER
;
1397 if (MemorySpaceMap
== NULL
) {
1398 return EFI_INVALID_PARAMETER
;
1401 CoreAcquireGcdMemoryLock ();
1404 // Count the number of descriptors
1406 *NumberOfDescriptors
= CoreCountGcdMapEntry (&mGcdMemorySpaceMap
);
1409 // Allocate the MemorySpaceMap
1411 *MemorySpaceMap
= AllocatePool (*NumberOfDescriptors
* sizeof (EFI_GCD_MEMORY_SPACE_DESCRIPTOR
));
1412 if (*MemorySpaceMap
== NULL
) {
1413 Status
= EFI_OUT_OF_RESOURCES
;
1418 // Fill in the MemorySpaceMap
1420 Descriptor
= *MemorySpaceMap
;
1421 Link
= mGcdMemorySpaceMap
.ForwardLink
;
1422 while (Link
!= &mGcdMemorySpaceMap
) {
1423 Entry
= CR (Link
, EFI_GCD_MAP_ENTRY
, Link
, EFI_GCD_MAP_SIGNATURE
);
1424 BuildMemoryDescriptor (Descriptor
, Entry
);
1426 Link
= Link
->ForwardLink
;
1428 Status
= EFI_SUCCESS
;
1431 CoreReleaseGcdMemoryLock ();
1437 Adds reserved I/O or I/O resources to the global coherency domain of the processor.
1439 @param GcdIoType IO type of the segment.
1440 @param BaseAddress Base address of the segment.
1441 @param Length Length of the segment.
1443 @retval EFI_SUCCESS Merged this segment into GCD map.
1444 @retval EFI_INVALID_PARAMETER Parameter not valid
1450 IN EFI_GCD_IO_TYPE GcdIoType
,
1451 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
1456 // Make sure parameters are valid
1458 if (GcdIoType
<= EfiGcdIoTypeNonExistent
|| GcdIoType
>= EfiGcdIoTypeMaximum
) {
1459 return EFI_INVALID_PARAMETER
;
1461 return CoreConvertSpace (GCD_ADD_IO_OPERATION
, (EFI_GCD_MEMORY_TYPE
) 0, GcdIoType
, BaseAddress
, Length
, 0, 0);
1466 Allocates nonexistent I/O, reserved I/O, or I/O resources from the global coherency
1467 domain of the processor.
1469 @param GcdAllocateType The type of allocate operation
1470 @param GcdIoType The desired IO type
1471 @param Alignment Align with 2^Alignment
1472 @param Length Length to allocate
1473 @param BaseAddress Base address to allocate
1474 @param ImageHandle The image handle consume the allocated space.
1475 @param DeviceHandle The device handle consume the allocated space.
1477 @retval EFI_INVALID_PARAMETER Invalid parameter.
1478 @retval EFI_NOT_FOUND No descriptor contains the desired space.
1479 @retval EFI_SUCCESS IO space successfully allocated.
1484 CoreAllocateIoSpace (
1485 IN EFI_GCD_ALLOCATE_TYPE GcdAllocateType
,
1486 IN EFI_GCD_IO_TYPE GcdIoType
,
1489 IN OUT EFI_PHYSICAL_ADDRESS
*BaseAddress
,
1490 IN EFI_HANDLE ImageHandle
,
1491 IN EFI_HANDLE DeviceHandle OPTIONAL
1494 return CoreAllocateSpace (
1495 GCD_ALLOCATE_IO_OPERATION
,
1497 (EFI_GCD_MEMORY_TYPE
) 0,
1509 Frees nonexistent I/O, reserved I/O, or I/O resources from the global coherency
1510 domain of the processor.
1512 @param BaseAddress Base address of the segment.
1513 @param Length Length of the segment.
1515 @retval EFI_SUCCESS Space successfully freed.
1521 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
1525 return CoreConvertSpace (GCD_FREE_IO_OPERATION
, (EFI_GCD_MEMORY_TYPE
) 0, (EFI_GCD_IO_TYPE
) 0, BaseAddress
, Length
, 0, 0);
1530 Removes reserved I/O or I/O resources from the global coherency domain of the
1533 @param BaseAddress Base address of the segment.
1534 @param Length Length of the segment.
1536 @retval EFI_SUCCESS Successfully removed a segment of IO space.
1542 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
1546 return CoreConvertSpace (GCD_REMOVE_IO_OPERATION
, (EFI_GCD_MEMORY_TYPE
) 0, (EFI_GCD_IO_TYPE
) 0, BaseAddress
, Length
, 0, 0);
1551 Build a IO descriptor according to an entry.
1553 @param Descriptor The descriptor to be built
1554 @param Entry According to this entry
1559 IN EFI_GCD_IO_SPACE_DESCRIPTOR
*Descriptor
,
1560 IN EFI_GCD_MAP_ENTRY
*Entry
1563 Descriptor
->BaseAddress
= Entry
->BaseAddress
;
1564 Descriptor
->Length
= Entry
->EndAddress
- Entry
->BaseAddress
+ 1;
1565 Descriptor
->GcdIoType
= Entry
->GcdIoType
;
1566 Descriptor
->ImageHandle
= Entry
->ImageHandle
;
1567 Descriptor
->DeviceHandle
= Entry
->DeviceHandle
;
1572 Retrieves the descriptor for an I/O region containing a specified address.
1574 @param BaseAddress Specified start address
1575 @param Descriptor Specified length
1577 @retval EFI_INVALID_PARAMETER Descriptor is NULL.
1578 @retval EFI_SUCCESS Successfully get the IO space descriptor.
1583 CoreGetIoSpaceDescriptor (
1584 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
1585 OUT EFI_GCD_IO_SPACE_DESCRIPTOR
*Descriptor
1589 LIST_ENTRY
*StartLink
;
1590 LIST_ENTRY
*EndLink
;
1591 EFI_GCD_MAP_ENTRY
*Entry
;
1594 // Make sure parameters are valid
1596 if (Descriptor
== NULL
) {
1597 return EFI_INVALID_PARAMETER
;
1600 CoreAcquireGcdIoLock ();
1603 // Search for the list of descriptors that contain BaseAddress
1605 Status
= CoreSearchGcdMapEntry (BaseAddress
, 1, &StartLink
, &EndLink
, &mGcdIoSpaceMap
);
1606 if (EFI_ERROR (Status
)) {
1607 Status
= EFI_NOT_FOUND
;
1610 // Copy the contents of the found descriptor into Descriptor
1612 Entry
= CR (StartLink
, EFI_GCD_MAP_ENTRY
, Link
, EFI_GCD_MAP_SIGNATURE
);
1613 BuildIoDescriptor (Descriptor
, Entry
);
1616 CoreReleaseGcdIoLock ();
1623 Returns a map of the I/O resources in the global coherency domain of the processor.
1625 @param NumberOfDescriptors Number of descriptors.
1626 @param IoSpaceMap Descriptor array
1628 @retval EFI_INVALID_PARAMETER Invalid parameter
1629 @retval EFI_OUT_OF_RESOURCES No enough buffer to allocate
1630 @retval EFI_SUCCESS Successfully get IO space map.
1636 OUT UINTN
*NumberOfDescriptors
,
1637 OUT EFI_GCD_IO_SPACE_DESCRIPTOR
**IoSpaceMap
1642 EFI_GCD_MAP_ENTRY
*Entry
;
1643 EFI_GCD_IO_SPACE_DESCRIPTOR
*Descriptor
;
1646 // Make sure parameters are valid
1648 if (NumberOfDescriptors
== NULL
) {
1649 return EFI_INVALID_PARAMETER
;
1651 if (IoSpaceMap
== NULL
) {
1652 return EFI_INVALID_PARAMETER
;
1655 CoreAcquireGcdIoLock ();
1658 // Count the number of descriptors
1660 *NumberOfDescriptors
= CoreCountGcdMapEntry (&mGcdIoSpaceMap
);
1663 // Allocate the IoSpaceMap
1665 *IoSpaceMap
= AllocatePool (*NumberOfDescriptors
* sizeof (EFI_GCD_IO_SPACE_DESCRIPTOR
));
1666 if (*IoSpaceMap
== NULL
) {
1667 Status
= EFI_OUT_OF_RESOURCES
;
1672 // Fill in the IoSpaceMap
1674 Descriptor
= *IoSpaceMap
;
1675 Link
= mGcdIoSpaceMap
.ForwardLink
;
1676 while (Link
!= &mGcdIoSpaceMap
) {
1677 Entry
= CR (Link
, EFI_GCD_MAP_ENTRY
, Link
, EFI_GCD_MAP_SIGNATURE
);
1678 BuildIoDescriptor (Descriptor
, Entry
);
1680 Link
= Link
->ForwardLink
;
1682 Status
= EFI_SUCCESS
;
1685 CoreReleaseGcdIoLock ();
1691 Converts a Resource Descriptor HOB attributes mask to an EFI Memory Descriptor
1694 @param GcdMemoryType Type of resource in the GCD memory map.
1695 @param Attributes The attribute mask in the Resource Descriptor
1698 @return The capabilities mask for an EFI Memory Descriptor.
1702 CoreConvertResourceDescriptorHobAttributesToCapabilities (
1703 EFI_GCD_MEMORY_TYPE GcdMemoryType
,
1707 UINT64 Capabilities
;
1708 GCD_ATTRIBUTE_CONVERSION_ENTRY
*Conversion
;
1711 // Convert the Resource HOB Attributes to an EFI Memory Capabilities mask
1713 for (Capabilities
= 0, Conversion
= mAttributeConversionTable
; Conversion
->Attribute
!= 0; Conversion
++) {
1714 if (Conversion
->Memory
|| (GcdMemoryType
!= EfiGcdMemoryTypeSystemMemory
)) {
1715 if (Attributes
& Conversion
->Attribute
) {
1716 Capabilities
|= Conversion
->Capability
;
1721 return Capabilities
;
1726 External function. Initializes memory services based on the memory
1727 descriptor HOBs. This function is responsible for priming the memory
1728 map, so memory allocations and resource allocations can be made.
1729 The first part of this function can not depend on any memory services
1730 until at least one memory descriptor is provided to the memory services.
1732 @param HobStart The start address of the HOB.
1733 @param MemoryBaseAddress Start address of memory region found to init DXE
1735 @param MemoryLength Length of memory region found to init DXE core.
1737 @retval EFI_SUCCESS Memory services successfully initialized.
1741 CoreInitializeMemoryServices (
1743 OUT EFI_PHYSICAL_ADDRESS
*MemoryBaseAddress
,
1744 OUT UINT64
*MemoryLength
1747 EFI_PEI_HOB_POINTERS Hob
;
1748 EFI_MEMORY_TYPE_INFORMATION
*EfiMemoryTypeInformation
;
1751 EFI_HOB_HANDOFF_INFO_TABLE
*PhitHob
;
1752 EFI_HOB_RESOURCE_DESCRIPTOR
*ResourceHob
;
1753 EFI_HOB_RESOURCE_DESCRIPTOR
*PhitResourceHob
;
1754 EFI_PHYSICAL_ADDRESS BaseAddress
;
1757 UINT64 Capabilities
;
1758 EFI_PHYSICAL_ADDRESS MaxMemoryBaseAddress
;
1759 UINT64 MaxMemoryLength
;
1760 UINT64 MaxMemoryAttributes
;
1761 EFI_PHYSICAL_ADDRESS MaxAddress
;
1762 EFI_PHYSICAL_ADDRESS HighAddress
;
1763 EFI_HOB_RESOURCE_DESCRIPTOR
*MaxResourceHob
;
1764 EFI_HOB_GUID_TYPE
*GuidHob
;
1767 // Point at the first HOB. This must be the PHIT HOB.
1769 Hob
.Raw
= *HobStart
;
1770 ASSERT (GET_HOB_TYPE (Hob
) == EFI_HOB_TYPE_HANDOFF
);
1773 // Initialize the spin locks and maps in the memory services.
1774 // Also fill in the memory services into the EFI Boot Services Table
1776 CoreInitializePool ();
1779 // Initialize Local Variables
1781 PhitResourceHob
= NULL
;
1782 MaxResourceHob
= NULL
;
1787 MaxMemoryBaseAddress
= 0;
1788 MaxMemoryLength
= 0;
1789 MaxMemoryAttributes
= 0;
1792 // Cache the PHIT HOB for later use
1794 PhitHob
= Hob
.HandoffInformationTable
;
1797 // See if a Memory Type Information HOB is available
1799 GuidHob
= GetFirstGuidHob (&gEfiMemoryTypeInformationGuid
);
1800 if (GuidHob
!= NULL
) {
1801 EfiMemoryTypeInformation
= GET_GUID_HOB_DATA (GuidHob
);
1802 DataSize
= GET_GUID_HOB_DATA_SIZE (GuidHob
);
1803 if (EfiMemoryTypeInformation
!= NULL
&& DataSize
> 0 && DataSize
<= (EfiMaxMemoryType
+ 1) * sizeof (EFI_MEMORY_TYPE_INFORMATION
)) {
1804 CopyMem (&gMemoryTypeInformation
, EfiMemoryTypeInformation
, DataSize
);
1809 // Find the Resource Descriptor HOB that contains range FreeMemoryBaseAddress..FreeMemoryLength
1813 for (Hob
.Raw
= *HobStart
; !END_OF_HOB_LIST(Hob
); Hob
.Raw
= GET_NEXT_HOB(Hob
)) {
1815 if (GET_HOB_TYPE (Hob
) == EFI_HOB_TYPE_RESOURCE_DESCRIPTOR
) {
1817 ResourceHob
= Hob
.ResourceDescriptor
;
1819 if (ResourceHob
->ResourceType
== EFI_RESOURCE_SYSTEM_MEMORY
&&
1820 (ResourceHob
->ResourceAttribute
& MEMORY_ATTRIBUTE_MASK
) == TESTED_MEMORY_ATTRIBUTES
) {
1822 if (PhitHob
->EfiFreeMemoryBottom
>= ResourceHob
->PhysicalStart
&&
1823 PhitHob
->EfiFreeMemoryTop
<= (ResourceHob
->PhysicalStart
+ ResourceHob
->ResourceLength
) ) {
1826 // Cache the resource descriptor HOB for the memory region described by the PHIT HOB
1828 PhitResourceHob
= ResourceHob
;
1831 Attributes
= PhitResourceHob
->ResourceAttribute
;
1832 BaseAddress
= PageAlignAddress (PhitHob
->EfiMemoryTop
);
1833 Length
= PageAlignLength (ResourceHob
->PhysicalStart
+ ResourceHob
->ResourceLength
- BaseAddress
);
1834 if (Length
< MINIMUM_INITIAL_MEMORY_SIZE
) {
1835 BaseAddress
= PageAlignAddress (PhitHob
->EfiFreeMemoryBottom
);
1836 Length
= PageAlignLength (PhitHob
->EfiFreeMemoryTop
- BaseAddress
);
1837 if (Length
< MINIMUM_INITIAL_MEMORY_SIZE
) {
1838 BaseAddress
= PageAlignAddress (ResourceHob
->PhysicalStart
);
1839 Length
= PageAlignLength ((UINT64
)((UINTN
)*HobStart
- BaseAddress
));
1849 // Assert if a resource descriptor HOB for the memory region described by the PHIT was not found
1854 // Search all the resource descriptor HOBs from the highest possible addresses down for a memory
1855 // region that is big enough to initialize the DXE core. Always skip the PHIT Resource HOB.
1856 // The max address must be within the physically addressible range for the processor.
1858 MaxMemoryLength
= 0;
1859 MaxAddress
= EFI_MAX_ADDRESS
;
1864 // Search for a tested memory region that is below MaxAddress
1866 for (Hob
.Raw
= *HobStart
; !END_OF_HOB_LIST(Hob
); Hob
.Raw
= GET_NEXT_HOB(Hob
)) {
1869 // See if this is a resource descriptor HOB that does not contain the PHIT.
1871 if (Hob
.ResourceDescriptor
!= PhitResourceHob
&& GET_HOB_TYPE (Hob
) == EFI_HOB_TYPE_RESOURCE_DESCRIPTOR
) {
1873 ResourceHob
= Hob
.ResourceDescriptor
;
1875 // See if this resource descrior HOB describes tested system memory below MaxAddress
1877 if (ResourceHob
->ResourceType
== EFI_RESOURCE_SYSTEM_MEMORY
&&
1878 (ResourceHob
->ResourceAttribute
& MEMORY_ATTRIBUTE_MASK
) == TESTED_MEMORY_ATTRIBUTES
&&
1879 ResourceHob
->PhysicalStart
+ ResourceHob
->ResourceLength
<= MaxAddress
) {
1881 // See if this is the highest tested system memory region below MaxAddress
1883 if (ResourceHob
->PhysicalStart
> HighAddress
) {
1885 MaxResourceHob
= ResourceHob
;
1886 HighAddress
= MaxResourceHob
->PhysicalStart
;
1894 // Compute the size of the tested memory region below MaxAddrees
1896 MaxMemoryBaseAddress
= PageAlignAddress (MaxResourceHob
->PhysicalStart
);
1897 MaxMemoryLength
= PageAlignLength (MaxResourceHob
->PhysicalStart
+ MaxResourceHob
->ResourceLength
- MaxMemoryBaseAddress
);
1898 MaxMemoryAttributes
= MaxResourceHob
->ResourceAttribute
;
1900 MaxAddress
= ResourceHob
->PhysicalStart
;
1901 } while (Found
&& MaxMemoryLength
< MINIMUM_INITIAL_MEMORY_SIZE
);
1903 if ((Length
< MINIMUM_INITIAL_MEMORY_SIZE
) ||
1904 (MaxMemoryBaseAddress
> BaseAddress
&& MaxMemoryLength
>= MINIMUM_INITIAL_MEMORY_SIZE
)) {
1905 BaseAddress
= MaxMemoryBaseAddress
;
1906 Length
= MaxMemoryLength
;
1907 Attributes
= MaxMemoryAttributes
;
1911 // If no memory regions are found that are big enough to initialize the DXE core, then ASSERT().
1913 ASSERT (Length
>= MINIMUM_INITIAL_MEMORY_SIZE
);
1916 // Convert the Resource HOB Attributes to an EFI Memory Capabilities mask
1918 Capabilities
= CoreConvertResourceDescriptorHobAttributesToCapabilities (EfiGcdMemoryTypeSystemMemory
, Attributes
);
1921 // Declare the very first memory region, so the EFI Memory Services are available.
1923 CoreAddMemoryDescriptor (
1924 EfiConventionalMemory
,
1926 RShiftU64 (Length
, EFI_PAGE_SHIFT
),
1930 *MemoryBaseAddress
= BaseAddress
;
1931 *MemoryLength
= Length
;
1938 External function. Initializes the GCD and memory services based on the memory
1939 descriptor HOBs. This function is responsible for priming the GCD map and the
1940 memory map, so memory allocations and resource allocations can be made. The
1941 HobStart will be relocated to a pool buffer.
1943 @param HobStart The start address of the HOB
1944 @param MemoryBaseAddress Start address of memory region found to init DXE
1946 @param MemoryLength Length of memory region found to init DXE core.
1948 @retval EFI_SUCCESS GCD services successfully initialized.
1952 CoreInitializeGcdServices (
1953 IN OUT VOID
**HobStart
,
1954 IN EFI_PHYSICAL_ADDRESS MemoryBaseAddress
,
1955 IN UINT64 MemoryLength
1958 EFI_PEI_HOB_POINTERS Hob
;
1960 EFI_HOB_HANDOFF_INFO_TABLE
*PhitHob
;
1961 UINT8 SizeOfMemorySpace
;
1962 UINT8 SizeOfIoSpace
;
1963 EFI_HOB_RESOURCE_DESCRIPTOR
*ResourceHob
;
1964 EFI_PHYSICAL_ADDRESS BaseAddress
;
1967 EFI_GCD_MAP_ENTRY
*Entry
;
1968 EFI_GCD_MEMORY_TYPE GcdMemoryType
;
1969 EFI_GCD_IO_TYPE GcdIoType
;
1970 EFI_GCD_MEMORY_SPACE_DESCRIPTOR Descriptor
;
1971 EFI_HOB_MEMORY_ALLOCATION
*MemoryHob
;
1972 EFI_HOB_FIRMWARE_VOLUME
*FirmwareVolumeHob
;
1973 UINTN NumberOfDescriptors
;
1974 EFI_GCD_MEMORY_SPACE_DESCRIPTOR
*MemorySpaceMap
;
1976 UINT64 Capabilities
;
1977 EFI_HOB_CPU
* CpuHob
;
1980 // Cache the PHIT HOB for later use
1982 PhitHob
= (EFI_HOB_HANDOFF_INFO_TABLE
*)(*HobStart
);
1985 // Get the number of address lines in the I/O and Memory space for the CPU
1987 CpuHob
= GetFirstHob (EFI_HOB_TYPE_CPU
);
1988 ASSERT (CpuHob
!= NULL
);
1989 SizeOfMemorySpace
= CpuHob
->SizeOfMemorySpace
;
1990 SizeOfIoSpace
= CpuHob
->SizeOfIoSpace
;
1993 // Initialize the GCD Memory Space Map
1995 Entry
= AllocateCopyPool (sizeof (EFI_GCD_MAP_ENTRY
), &mGcdMemorySpaceMapEntryTemplate
);
1996 ASSERT (Entry
!= NULL
);
1998 Entry
->EndAddress
= LShiftU64 (1, SizeOfMemorySpace
) - 1;
2000 InsertHeadList (&mGcdMemorySpaceMap
, &Entry
->Link
);
2003 // Initialize the GCD I/O Space Map
2005 Entry
= AllocateCopyPool (sizeof (EFI_GCD_MAP_ENTRY
), &mGcdIoSpaceMapEntryTemplate
);
2006 ASSERT (Entry
!= NULL
);
2008 Entry
->EndAddress
= LShiftU64 (1, SizeOfIoSpace
) - 1;
2010 InsertHeadList (&mGcdIoSpaceMap
, &Entry
->Link
);
2013 // Walk the HOB list and add all resource descriptors to the GCD
2015 for (Hob
.Raw
= *HobStart
; !END_OF_HOB_LIST(Hob
); Hob
.Raw
= GET_NEXT_HOB(Hob
)) {
2017 GcdMemoryType
= EfiGcdMemoryTypeNonExistent
;
2018 GcdIoType
= EfiGcdIoTypeNonExistent
;
2020 if (GET_HOB_TYPE (Hob
) == EFI_HOB_TYPE_RESOURCE_DESCRIPTOR
) {
2022 ResourceHob
= Hob
.ResourceDescriptor
;
2024 switch (ResourceHob
->ResourceType
) {
2025 case EFI_RESOURCE_SYSTEM_MEMORY
:
2026 if ((ResourceHob
->ResourceAttribute
& MEMORY_ATTRIBUTE_MASK
) == TESTED_MEMORY_ATTRIBUTES
) {
2027 GcdMemoryType
= EfiGcdMemoryTypeSystemMemory
;
2029 if ((ResourceHob
->ResourceAttribute
& MEMORY_ATTRIBUTE_MASK
) == INITIALIZED_MEMORY_ATTRIBUTES
) {
2030 GcdMemoryType
= EfiGcdMemoryTypeReserved
;
2032 if ((ResourceHob
->ResourceAttribute
& MEMORY_ATTRIBUTE_MASK
) == PRESENT_MEMORY_ATTRIBUTES
) {
2033 GcdMemoryType
= EfiGcdMemoryTypeReserved
;
2036 case EFI_RESOURCE_MEMORY_MAPPED_IO
:
2037 case EFI_RESOURCE_FIRMWARE_DEVICE
:
2038 GcdMemoryType
= EfiGcdMemoryTypeMemoryMappedIo
;
2040 case EFI_RESOURCE_MEMORY_MAPPED_IO_PORT
:
2041 case EFI_RESOURCE_MEMORY_RESERVED
:
2042 GcdMemoryType
= EfiGcdMemoryTypeReserved
;
2044 case EFI_RESOURCE_IO
:
2045 GcdIoType
= EfiGcdIoTypeIo
;
2047 case EFI_RESOURCE_IO_RESERVED
:
2048 GcdIoType
= EfiGcdIoTypeReserved
;
2052 if (GcdMemoryType
!= EfiGcdMemoryTypeNonExistent
) {
2054 // Convert the Resource HOB Attributes to an EFI Memory Capabilities mask
2056 Capabilities
= CoreConvertResourceDescriptorHobAttributesToCapabilities (
2058 ResourceHob
->ResourceAttribute
2061 Status
= CoreInternalAddMemorySpace (
2063 ResourceHob
->PhysicalStart
,
2064 ResourceHob
->ResourceLength
,
2069 if (GcdIoType
!= EfiGcdIoTypeNonExistent
) {
2070 Status
= CoreAddIoSpace (
2072 ResourceHob
->PhysicalStart
,
2073 ResourceHob
->ResourceLength
2080 // Allocate first memory region from the GCD by the DXE core
2082 Status
= CoreAllocateMemorySpace (
2083 EfiGcdAllocateAddress
,
2084 EfiGcdMemoryTypeSystemMemory
,
2088 gDxeCoreImageHandle
,
2093 // Walk the HOB list and allocate all memory space that is consumed by memory allocation HOBs,
2094 // and Firmware Volume HOBs. Also update the EFI Memory Map with the memory allocation HOBs.
2096 for (Hob
.Raw
= *HobStart
; !END_OF_HOB_LIST(Hob
); Hob
.Raw
= GET_NEXT_HOB(Hob
)) {
2097 if (GET_HOB_TYPE (Hob
) == EFI_HOB_TYPE_MEMORY_ALLOCATION
) {
2098 MemoryHob
= Hob
.MemoryAllocation
;
2099 BaseAddress
= MemoryHob
->AllocDescriptor
.MemoryBaseAddress
;
2100 Status
= CoreGetMemorySpaceDescriptor (BaseAddress
, &Descriptor
);
2101 if (!EFI_ERROR (Status
)) {
2102 Status
= CoreAllocateMemorySpace (
2103 EfiGcdAllocateAddress
,
2104 Descriptor
.GcdMemoryType
,
2106 MemoryHob
->AllocDescriptor
.MemoryLength
,
2108 gDxeCoreImageHandle
,
2111 if (!EFI_ERROR (Status
) && Descriptor
.GcdMemoryType
== EfiGcdMemoryTypeSystemMemory
) {
2112 CoreAddMemoryDescriptor (
2113 MemoryHob
->AllocDescriptor
.MemoryType
,
2114 MemoryHob
->AllocDescriptor
.MemoryBaseAddress
,
2115 RShiftU64 (MemoryHob
->AllocDescriptor
.MemoryLength
, EFI_PAGE_SHIFT
),
2116 Descriptor
.Capabilities
& (~EFI_MEMORY_RUNTIME
)
2122 if (GET_HOB_TYPE (Hob
) == EFI_HOB_TYPE_FV
) {
2123 FirmwareVolumeHob
= Hob
.FirmwareVolume
;
2124 BaseAddress
= FirmwareVolumeHob
->BaseAddress
;
2125 Status
= CoreAllocateMemorySpace (
2126 EfiGcdAllocateAddress
,
2127 EfiGcdMemoryTypeMemoryMappedIo
,
2129 FirmwareVolumeHob
->Length
,
2131 gDxeCoreImageHandle
,
2138 // Relocate HOB List to an allocated pool buffer.
2140 NewHobList
= AllocateCopyPool (
2141 (UINTN
)PhitHob
->EfiFreeMemoryBottom
- (UINTN
)(*HobStart
),
2144 ASSERT (NewHobList
!= NULL
);
2146 *HobStart
= NewHobList
;
2147 gHobList
= NewHobList
;
2150 // Add and allocate the remaining unallocated system memory to the memory services.
2152 Status
= CoreGetMemorySpaceMap (&NumberOfDescriptors
, &MemorySpaceMap
);
2153 for (Index
= 0; Index
< NumberOfDescriptors
; Index
++) {
2154 if (MemorySpaceMap
[Index
].GcdMemoryType
== EfiGcdMemoryTypeSystemMemory
) {
2155 if (MemorySpaceMap
[Index
].ImageHandle
== NULL
) {
2156 BaseAddress
= PageAlignAddress (MemorySpaceMap
[Index
].BaseAddress
);
2157 Length
= PageAlignLength (MemorySpaceMap
[Index
].BaseAddress
+ MemorySpaceMap
[Index
].Length
- BaseAddress
);
2158 if (Length
== 0 || MemorySpaceMap
[Index
].BaseAddress
+ MemorySpaceMap
[Index
].Length
< BaseAddress
) {
2161 CoreAddMemoryDescriptor (
2162 EfiConventionalMemory
,
2164 RShiftU64 (Length
, EFI_PAGE_SHIFT
),
2165 MemorySpaceMap
[Index
].Capabilities
& (~EFI_MEMORY_RUNTIME
)
2167 Status
= CoreAllocateMemorySpace (
2168 EfiGcdAllocateAddress
,
2169 EfiGcdMemoryTypeSystemMemory
,
2173 gDxeCoreImageHandle
,
2179 CoreFreePool (MemorySpaceMap
);