3 The file contains the GCD related services in the EFI Boot Services Table.
4 The GCD services are used to manage the memory and I/O regions that
5 are accessible to the CPU that is executing the DXE core.
7 Copyright (c) 2006 - 2008, Intel Corporation
8 All rights reserved. This program and the accompanying materials
9 are licensed and made available under the terms and conditions of the BSD License
10 which accompanies this distribution. The full text of the license may be found at
11 http://opensource.org/licenses/bsd-license.php
13 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
14 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
20 #define MINIMUM_INITIAL_MEMORY_SIZE 0x10000
22 #define MEMORY_ATTRIBUTE_MASK (EFI_RESOURCE_ATTRIBUTE_PRESENT | \
23 EFI_RESOURCE_ATTRIBUTE_INITIALIZED | \
24 EFI_RESOURCE_ATTRIBUTE_TESTED | \
25 EFI_RESOURCE_ATTRIBUTE_READ_PROTECTED | \
26 EFI_RESOURCE_ATTRIBUTE_WRITE_PROTECTED | \
27 EFI_RESOURCE_ATTRIBUTE_EXECUTION_PROTECTED | \
28 EFI_RESOURCE_ATTRIBUTE_16_BIT_IO | \
29 EFI_RESOURCE_ATTRIBUTE_32_BIT_IO | \
30 EFI_RESOURCE_ATTRIBUTE_64_BIT_IO )
32 #define TESTED_MEMORY_ATTRIBUTES (EFI_RESOURCE_ATTRIBUTE_PRESENT | \
33 EFI_RESOURCE_ATTRIBUTE_INITIALIZED | \
34 EFI_RESOURCE_ATTRIBUTE_TESTED )
36 #define INITIALIZED_MEMORY_ATTRIBUTES (EFI_RESOURCE_ATTRIBUTE_PRESENT | \
37 EFI_RESOURCE_ATTRIBUTE_INITIALIZED )
39 #define PRESENT_MEMORY_ATTRIBUTES (EFI_RESOURCE_ATTRIBUTE_PRESENT)
41 #define INVALID_CPU_ARCH_ATTRIBUTES 0xffffffff
46 EFI_LOCK mGcdMemorySpaceLock
= EFI_INITIALIZE_LOCK_VARIABLE (TPL_NOTIFY
);
47 EFI_LOCK mGcdIoSpaceLock
= EFI_INITIALIZE_LOCK_VARIABLE (TPL_NOTIFY
);
48 LIST_ENTRY mGcdMemorySpaceMap
= INITIALIZE_LIST_HEAD_VARIABLE (mGcdMemorySpaceMap
);
49 LIST_ENTRY mGcdIoSpaceMap
= INITIALIZE_LIST_HEAD_VARIABLE (mGcdIoSpaceMap
);
51 EFI_GCD_MAP_ENTRY mGcdMemorySpaceMapEntryTemplate
= {
52 EFI_GCD_MAP_SIGNATURE
,
58 EfiGcdMemoryTypeNonExistent
,
64 EFI_GCD_MAP_ENTRY mGcdIoSpaceMapEntryTemplate
= {
65 EFI_GCD_MAP_SIGNATURE
,
71 (EFI_GCD_MEMORY_TYPE
) 0,
72 EfiGcdIoTypeNonExistent
,
77 GCD_ATTRIBUTE_CONVERSION_ENTRY mAttributeConversionTable
[] = {
78 { EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE
, EFI_MEMORY_UC
, TRUE
},
79 { EFI_RESOURCE_ATTRIBUTE_UNCACHED_EXPORTED
, EFI_MEMORY_UCE
, TRUE
},
80 { EFI_RESOURCE_ATTRIBUTE_WRITE_COMBINEABLE
, EFI_MEMORY_WC
, TRUE
},
81 { EFI_RESOURCE_ATTRIBUTE_WRITE_THROUGH_CACHEABLE
, EFI_MEMORY_WT
, TRUE
},
82 { EFI_RESOURCE_ATTRIBUTE_WRITE_BACK_CACHEABLE
, EFI_MEMORY_WB
, TRUE
},
83 { EFI_RESOURCE_ATTRIBUTE_READ_PROTECTED
, EFI_MEMORY_RP
, TRUE
},
84 { EFI_RESOURCE_ATTRIBUTE_WRITE_PROTECTED
, EFI_MEMORY_WP
, TRUE
},
85 { EFI_RESOURCE_ATTRIBUTE_EXECUTION_PROTECTED
, EFI_MEMORY_XP
, TRUE
},
86 { EFI_RESOURCE_ATTRIBUTE_PRESENT
, EFI_MEMORY_PRESENT
, FALSE
},
87 { EFI_RESOURCE_ATTRIBUTE_INITIALIZED
, EFI_MEMORY_INITIALIZED
, FALSE
},
88 { EFI_RESOURCE_ATTRIBUTE_TESTED
, EFI_MEMORY_TESTED
, FALSE
},
94 Acquire memory lock on mGcdMemorySpaceLock.
98 CoreAcquireGcdMemoryLock (
102 CoreAcquireLock (&mGcdMemorySpaceLock
);
108 Release memory lock on mGcdMemorySpaceLock.
112 CoreReleaseGcdMemoryLock (
116 CoreReleaseLock (&mGcdMemorySpaceLock
);
122 Acquire memory lock on mGcdIoSpaceLock.
127 CoreAcquireGcdIoLock (
131 CoreAcquireLock (&mGcdIoSpaceLock
);
136 Release memory lock on mGcdIoSpaceLock.
141 CoreReleaseGcdIoLock (
145 CoreReleaseLock (&mGcdIoSpaceLock
);
151 // GCD Initialization Worker Functions
155 Aligns a value to the specified boundary.
157 @param Value 64 bit value to align
158 @param Alignment Log base 2 of the boundary to align Value to
159 @param RoundUp TRUE if Value is to be rounded up to the nearest
160 aligned boundary. FALSE is Value is to be
161 rounded down to the nearest aligned boundary.
163 @return A 64 bit value is the aligned to the value nearest Value with an alignment by Alignment.
174 UINT64 AlignmentMask
;
176 AlignmentMask
= LShiftU64 (1, Alignment
) - 1;
178 Value
+= AlignmentMask
;
180 return Value
& (~AlignmentMask
);
185 Aligns address to the page boundary.
187 @param Value 64 bit address to align
189 @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.
216 return AlignValue (Value
, EFI_PAGE_SHIFT
, FALSE
);
220 // GCD Memory Space Worker Functions
224 Allocate pool for two entries.
226 @param TopEntry An entry of GCD map
227 @param BottomEntry An entry of GCD map
229 @retval EFI_OUT_OF_RESOURCES No enough buffer to be allocated.
230 @retval EFI_SUCCESS Both entries successfully allocated.
235 CoreAllocateGcdMapEntry (
236 IN OUT EFI_GCD_MAP_ENTRY
**TopEntry
,
237 IN OUT EFI_GCD_MAP_ENTRY
**BottomEntry
240 *TopEntry
= CoreAllocateZeroBootServicesPool (sizeof (EFI_GCD_MAP_ENTRY
));
241 if (*TopEntry
== NULL
) {
242 return EFI_OUT_OF_RESOURCES
;
245 *BottomEntry
= CoreAllocateZeroBootServicesPool (sizeof (EFI_GCD_MAP_ENTRY
));
246 if (*BottomEntry
== NULL
) {
247 CoreFreePool (*TopEntry
);
248 return EFI_OUT_OF_RESOURCES
;
256 Internal function. Inserts a new descriptor into a sorted list
258 @param Link The linked list to insert the range BaseAddress
260 @param Entry A pointer to the entry that is inserted
261 @param BaseAddress The base address of the new range
262 @param Length The length of the new range in bytes
263 @param TopEntry Top pad entry to insert if needed.
264 @param BottomEntry Bottom pad entry to insert if needed.
266 @retval EFI_SUCCESS The new range was inserted into the linked list
271 CoreInsertGcdMapEntry (
273 IN EFI_GCD_MAP_ENTRY
*Entry
,
274 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
276 IN EFI_GCD_MAP_ENTRY
*TopEntry
,
277 IN EFI_GCD_MAP_ENTRY
*BottomEntry
280 ASSERT (Length
!= 0);
281 ASSERT (TopEntry
->Signature
== 0);
282 ASSERT (BottomEntry
->Signature
== 0);
284 if (BaseAddress
> Entry
->BaseAddress
) {
285 CopyMem (BottomEntry
, Entry
, sizeof (EFI_GCD_MAP_ENTRY
));
286 Entry
->BaseAddress
= BaseAddress
;
287 BottomEntry
->EndAddress
= BaseAddress
- 1;
288 InsertTailList (Link
, &BottomEntry
->Link
);
291 if ((BaseAddress
+ Length
- 1) < Entry
->EndAddress
) {
292 CopyMem (TopEntry
, Entry
, sizeof (EFI_GCD_MAP_ENTRY
));
293 TopEntry
->BaseAddress
= BaseAddress
+ Length
;
294 Entry
->EndAddress
= BaseAddress
+ Length
- 1;
295 InsertHeadList (Link
, &TopEntry
->Link
);
303 Merge the Gcd region specified by Link and its adjacent entry
305 @param Link Specify the entry to be merged (with its
307 @param Forward Direction (forward or backward).
310 @retval EFI_SUCCESS Successfully returned.
311 @retval EFI_UNSUPPORTED These adjacent regions could not merge.
316 CoreMergeGcdMapEntry (
322 LIST_ENTRY
*AdjacentLink
;
323 EFI_GCD_MAP_ENTRY
*Entry
;
324 EFI_GCD_MAP_ENTRY
*AdjacentEntry
;
327 // Get adjacent entry
330 AdjacentLink
= Link
->ForwardLink
;
332 AdjacentLink
= Link
->BackLink
;
336 // If AdjacentLink is the head of the list, then no merge can be performed
338 if (AdjacentLink
== Map
) {
342 Entry
= CR (Link
, EFI_GCD_MAP_ENTRY
, Link
, EFI_GCD_MAP_SIGNATURE
);
343 AdjacentEntry
= CR (AdjacentLink
, EFI_GCD_MAP_ENTRY
, Link
, EFI_GCD_MAP_SIGNATURE
);
345 if (Entry
->Capabilities
!= AdjacentEntry
->Capabilities
) {
346 return EFI_UNSUPPORTED
;
348 if (Entry
->Attributes
!= AdjacentEntry
->Attributes
) {
349 return EFI_UNSUPPORTED
;
351 if (Entry
->GcdMemoryType
!= AdjacentEntry
->GcdMemoryType
) {
352 return EFI_UNSUPPORTED
;
354 if (Entry
->GcdIoType
!= AdjacentEntry
->GcdIoType
) {
355 return EFI_UNSUPPORTED
;
357 if (Entry
->ImageHandle
!= AdjacentEntry
->ImageHandle
) {
358 return EFI_UNSUPPORTED
;
360 if (Entry
->DeviceHandle
!= AdjacentEntry
->DeviceHandle
) {
361 return EFI_UNSUPPORTED
;
365 Entry
->EndAddress
= AdjacentEntry
->EndAddress
;
367 Entry
->BaseAddress
= AdjacentEntry
->BaseAddress
;
369 RemoveEntryList (AdjacentLink
);
370 CoreFreePool (AdjacentEntry
);
377 Merge adjacent entries on total chain.
379 @param TopEntry Top entry of GCD map.
380 @param BottomEntry Bottom entry of GCD map.
381 @param StartLink Start link of the list for this loop.
382 @param EndLink End link of the list for this loop.
385 @retval EFI_SUCCESS GCD map successfully cleaned up.
390 CoreCleanupGcdMapEntry (
391 IN EFI_GCD_MAP_ENTRY
*TopEntry
,
392 IN EFI_GCD_MAP_ENTRY
*BottomEntry
,
393 IN LIST_ENTRY
*StartLink
,
394 IN LIST_ENTRY
*EndLink
,
400 if (TopEntry
->Signature
== 0) {
401 CoreFreePool (TopEntry
);
403 if (BottomEntry
->Signature
== 0) {
404 CoreFreePool (BottomEntry
);
408 while (Link
!= EndLink
->ForwardLink
) {
409 CoreMergeGcdMapEntry (Link
, FALSE
, Map
);
410 Link
= Link
->ForwardLink
;
412 CoreMergeGcdMapEntry (EndLink
, TRUE
, Map
);
419 Search a segment of memory space in GCD map. The result is a range of GCD entry list.
421 @param BaseAddress The start address of the segment.
422 @param Length The length of the segment.
423 @param StartLink The first GCD entry involves this segment of
425 @param EndLink The first GCD entry involves this segment of
427 @param Map Points to the start entry to search.
429 @retval EFI_SUCCESS Successfully found the entry.
430 @retval EFI_NOT_FOUND Not found.
435 CoreSearchGcdMapEntry (
436 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
438 OUT LIST_ENTRY
**StartLink
,
439 OUT LIST_ENTRY
**EndLink
,
444 EFI_GCD_MAP_ENTRY
*Entry
;
446 ASSERT (Length
!= 0);
451 Link
= Map
->ForwardLink
;
452 while (Link
!= Map
) {
453 Entry
= CR (Link
, EFI_GCD_MAP_ENTRY
, Link
, EFI_GCD_MAP_SIGNATURE
);
454 if (BaseAddress
>= Entry
->BaseAddress
&& BaseAddress
<= Entry
->EndAddress
) {
457 if (*StartLink
!= NULL
) {
458 if ((BaseAddress
+ Length
- 1) >= Entry
->BaseAddress
&&
459 (BaseAddress
+ Length
- 1) <= Entry
->EndAddress
) {
464 Link
= Link
->ForwardLink
;
466 return EFI_NOT_FOUND
;
471 Count the amount of GCD map entries.
473 @param Map Points to the start entry to do the count loop.
480 CoreCountGcdMapEntry (
488 Link
= Map
->ForwardLink
;
489 while (Link
!= Map
) {
491 Link
= Link
->ForwardLink
;
499 Return the memory attribute specified by Attributes
501 @param Attributes A num with some attribute bits on.
503 @return The enum value of memory attribute.
508 ConverToCpuArchAttributes (
512 if ( (Attributes
& EFI_MEMORY_UC
) == EFI_MEMORY_UC
) {
513 return EFI_MEMORY_UC
;
516 if ( (Attributes
& EFI_MEMORY_WC
) == EFI_MEMORY_WC
) {
517 return EFI_MEMORY_WC
;
520 if ( (Attributes
& EFI_MEMORY_WT
) == EFI_MEMORY_WT
) {
521 return EFI_MEMORY_WT
;
524 if ( (Attributes
& EFI_MEMORY_WB
) == EFI_MEMORY_WB
) {
525 return EFI_MEMORY_WB
;
528 if ( (Attributes
& EFI_MEMORY_WP
) == EFI_MEMORY_WP
) {
529 return EFI_MEMORY_WP
;
532 return INVALID_CPU_ARCH_ATTRIBUTES
;
538 Do operation on a segment of memory space specified (add, free, remove, change attribute ...).
540 @param Operation The type of the operation
541 @param GcdMemoryType Additional information for the operation
542 @param GcdIoType Additional information for the operation
543 @param BaseAddress Start address of the segment
544 @param Length length of the segment
545 @param Capabilities The alterable attributes of a newly added entry
546 @param Attributes The attributes needs to be set
548 @retval EFI_INVALID_PARAMETER Length is 0 or address (length) not aligned when
550 @retval EFI_SUCCESS Action successfully done.
551 @retval EFI_UNSUPPORTED Could not find the proper descriptor on this
552 segment or set an upsupported attribute.
553 @retval EFI_ACCESS_DENIED Operate on an space non-exist or is used for an
555 @retval EFI_NOT_FOUND Free a non-using space or remove a non-exist
557 @retval EFI_OUT_OF_RESOURCES No buffer could be allocated.
564 IN EFI_GCD_MEMORY_TYPE GcdMemoryType
,
565 IN EFI_GCD_IO_TYPE GcdIoType
,
566 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
568 IN UINT64 Capabilities
,
575 EFI_GCD_MAP_ENTRY
*Entry
;
576 EFI_GCD_MAP_ENTRY
*TopEntry
;
577 EFI_GCD_MAP_ENTRY
*BottomEntry
;
578 LIST_ENTRY
*StartLink
;
581 EFI_CPU_ARCH_PROTOCOL
*CpuArch
;
582 UINT64 CpuArchAttributes
;
585 return EFI_INVALID_PARAMETER
;
589 if (Operation
& GCD_MEMORY_SPACE_OPERATION
) {
590 CoreAcquireGcdMemoryLock ();
591 Map
= &mGcdMemorySpaceMap
;
593 if (Operation
& GCD_IO_SPACE_OPERATION
) {
594 CoreAcquireGcdIoLock ();
595 Map
= &mGcdIoSpaceMap
;
599 // Search for the list of descriptors that cover the range BaseAddress to BaseAddress+Length
601 Status
= CoreSearchGcdMapEntry (BaseAddress
, Length
, &StartLink
, &EndLink
, Map
);
602 if (EFI_ERROR (Status
)) {
603 Status
= EFI_UNSUPPORTED
;
609 // Verify that the list of descriptors are unallocated non-existent memory.
612 while (Link
!= EndLink
->ForwardLink
) {
613 Entry
= CR (Link
, EFI_GCD_MAP_ENTRY
, Link
, EFI_GCD_MAP_SIGNATURE
);
618 case GCD_ADD_MEMORY_OPERATION
:
619 if (Entry
->GcdMemoryType
!= EfiGcdMemoryTypeNonExistent
||
620 Entry
->ImageHandle
!= NULL
) {
621 Status
= EFI_ACCESS_DENIED
;
625 case GCD_ADD_IO_OPERATION
:
626 if (Entry
->GcdIoType
!= EfiGcdIoTypeNonExistent
||
627 Entry
->ImageHandle
!= NULL
) {
628 Status
= EFI_ACCESS_DENIED
;
635 case GCD_FREE_MEMORY_OPERATION
:
636 case GCD_FREE_IO_OPERATION
:
637 if (Entry
->ImageHandle
== NULL
) {
638 Status
= EFI_NOT_FOUND
;
645 case GCD_REMOVE_MEMORY_OPERATION
:
646 if (Entry
->GcdMemoryType
== EfiGcdMemoryTypeNonExistent
) {
647 Status
= EFI_NOT_FOUND
;
650 if (Entry
->ImageHandle
!= NULL
) {
651 Status
= EFI_ACCESS_DENIED
;
655 case GCD_REMOVE_IO_OPERATION
:
656 if (Entry
->GcdIoType
== EfiGcdIoTypeNonExistent
) {
657 Status
= EFI_NOT_FOUND
;
660 if (Entry
->ImageHandle
!= NULL
) {
661 Status
= EFI_ACCESS_DENIED
;
666 // Set attribute operations
668 case GCD_SET_ATTRIBUTES_MEMORY_OPERATION
:
669 if (Attributes
& EFI_MEMORY_RUNTIME
) {
670 if ((BaseAddress
& EFI_PAGE_MASK
) != 0 || (Length
& EFI_PAGE_MASK
) != 0) {
671 Status
= EFI_INVALID_PARAMETER
;
676 if ((Entry
->Capabilities
& Attributes
) != Attributes
) {
677 Status
= EFI_UNSUPPORTED
;
682 Link
= Link
->ForwardLink
;
686 // Allocate work space to perform this operation
688 Status
= CoreAllocateGcdMapEntry (&TopEntry
, &BottomEntry
);
689 if (EFI_ERROR (Status
)) {
690 Status
= EFI_OUT_OF_RESOURCES
;
697 if (Operation
== GCD_SET_ATTRIBUTES_MEMORY_OPERATION
) {
699 // Call CPU Arch Protocol to attempt to set attributes on the range
701 CpuArchAttributes
= ConverToCpuArchAttributes (Attributes
);
702 if ( CpuArchAttributes
!= INVALID_CPU_ARCH_ATTRIBUTES
) {
703 Status
= CoreLocateProtocol (&gEfiCpuArchProtocolGuid
, NULL
, (VOID
**)&CpuArch
);
704 if (EFI_ERROR (Status
)) {
705 Status
= EFI_ACCESS_DENIED
;
709 Status
= CpuArch
->SetMemoryAttributes (
715 if (EFI_ERROR (Status
)) {
723 // Convert/Insert the list of descriptors from StartLink to EndLink
726 while (Link
!= EndLink
->ForwardLink
) {
727 Entry
= CR (Link
, EFI_GCD_MAP_ENTRY
, Link
, EFI_GCD_MAP_SIGNATURE
);
728 CoreInsertGcdMapEntry (Link
, Entry
, BaseAddress
, Length
, TopEntry
, BottomEntry
);
733 case GCD_ADD_MEMORY_OPERATION
:
734 Entry
->GcdMemoryType
= GcdMemoryType
;
735 if (GcdMemoryType
== EfiGcdMemoryTypeMemoryMappedIo
) {
736 Entry
->Capabilities
= Capabilities
| EFI_MEMORY_RUNTIME
| EFI_MEMORY_PORT_IO
;
738 Entry
->Capabilities
= Capabilities
| EFI_MEMORY_RUNTIME
;
741 case GCD_ADD_IO_OPERATION
:
742 Entry
->GcdIoType
= GcdIoType
;
747 case GCD_FREE_MEMORY_OPERATION
:
748 case GCD_FREE_IO_OPERATION
:
749 Entry
->ImageHandle
= NULL
;
750 Entry
->DeviceHandle
= NULL
;
755 case GCD_REMOVE_MEMORY_OPERATION
:
756 Entry
->GcdMemoryType
= EfiGcdMemoryTypeNonExistent
;
757 Entry
->Capabilities
= 0;
759 case GCD_REMOVE_IO_OPERATION
:
760 Entry
->GcdIoType
= EfiGcdIoTypeNonExistent
;
763 // Set attribute operations
765 case GCD_SET_ATTRIBUTES_MEMORY_OPERATION
:
766 Entry
->Attributes
= Attributes
;
769 Link
= Link
->ForwardLink
;
775 Status
= CoreCleanupGcdMapEntry (TopEntry
, BottomEntry
, StartLink
, EndLink
, Map
);
778 if (Operation
& GCD_MEMORY_SPACE_OPERATION
) {
779 CoreReleaseGcdMemoryLock ();
781 if (Operation
& GCD_IO_SPACE_OPERATION
) {
782 CoreReleaseGcdIoLock ();
790 Check whether an entry could be used to allocate space.
792 @param Operation Allocate memory or IO
793 @param Entry The entry to be tested
794 @param GcdMemoryType The desired memory type
795 @param GcdIoType The desired IO type
797 @retval EFI_NOT_FOUND The memory type does not match or there's an
798 image handle on the entry.
799 @retval EFI_UNSUPPORTED The operation unsupported.
800 @retval EFI_SUCCESS It's ok for this entry to be used to allocate
806 CoreAllocateSpaceCheckEntry (
808 IN EFI_GCD_MAP_ENTRY
*Entry
,
809 IN EFI_GCD_MEMORY_TYPE GcdMemoryType
,
810 IN EFI_GCD_IO_TYPE GcdIoType
813 if (Entry
->ImageHandle
!= NULL
) {
814 return EFI_NOT_FOUND
;
817 case GCD_ALLOCATE_MEMORY_OPERATION
:
818 if (Entry
->GcdMemoryType
!= GcdMemoryType
) {
819 return EFI_NOT_FOUND
;
822 case GCD_ALLOCATE_IO_OPERATION
:
823 if (Entry
->GcdIoType
!= GcdIoType
) {
824 return EFI_NOT_FOUND
;
828 return EFI_UNSUPPORTED
;
835 Allocate space on specified address and length.
837 @param Operation The type of operation (memory or IO)
838 @param GcdAllocateType The type of allocate operation
839 @param GcdMemoryType The desired memory type
840 @param GcdIoType The desired IO type
841 @param Alignment Align with 2^Alignment
842 @param Length Length to allocate
843 @param BaseAddress Base address to allocate
844 @param ImageHandle The image handle consume the allocated space.
845 @param DeviceHandle The device handle consume the allocated space.
847 @retval EFI_INVALID_PARAMETER Invalid parameter.
848 @retval EFI_NOT_FOUND No descriptor for the desired space exists.
849 @retval EFI_SUCCESS Space successfully allocated.
856 IN EFI_GCD_ALLOCATE_TYPE GcdAllocateType
,
857 IN EFI_GCD_MEMORY_TYPE GcdMemoryType
,
858 IN EFI_GCD_IO_TYPE GcdIoType
,
861 IN OUT EFI_PHYSICAL_ADDRESS
*BaseAddress
,
862 IN EFI_HANDLE ImageHandle
,
863 IN EFI_HANDLE DeviceHandle OPTIONAL
867 EFI_PHYSICAL_ADDRESS AlignmentMask
;
868 EFI_PHYSICAL_ADDRESS MaxAddress
;
872 EFI_GCD_MAP_ENTRY
*Entry
;
873 EFI_GCD_MAP_ENTRY
*TopEntry
;
874 EFI_GCD_MAP_ENTRY
*BottomEntry
;
875 LIST_ENTRY
*StartLink
;
880 // Make sure parameters are valid
882 if (GcdAllocateType
< 0 || GcdAllocateType
>= EfiGcdMaxAllocateType
) {
883 return EFI_INVALID_PARAMETER
;
885 if (GcdMemoryType
< 0 || GcdMemoryType
>= EfiGcdMemoryTypeMaximum
) {
886 return EFI_INVALID_PARAMETER
;
888 if (GcdIoType
< 0 || GcdIoType
>= EfiGcdIoTypeMaximum
) {
889 return EFI_INVALID_PARAMETER
;
891 if (BaseAddress
== NULL
) {
892 return EFI_INVALID_PARAMETER
;
894 if (ImageHandle
== NULL
) {
895 return EFI_INVALID_PARAMETER
;
897 if (Alignment
>= 64) {
898 return EFI_NOT_FOUND
;
901 return EFI_INVALID_PARAMETER
;
905 if (Operation
& GCD_MEMORY_SPACE_OPERATION
) {
906 CoreAcquireGcdMemoryLock ();
907 Map
= &mGcdMemorySpaceMap
;
909 if (Operation
& GCD_IO_SPACE_OPERATION
) {
910 CoreAcquireGcdIoLock ();
911 Map
= &mGcdIoSpaceMap
;
918 // Compute alignment bit mask
920 AlignmentMask
= LShiftU64 (1, Alignment
) - 1;
922 if (GcdAllocateType
== EfiGcdAllocateAddress
) {
924 // Verify that the BaseAddress passed in is aligned correctly
926 if ((*BaseAddress
& AlignmentMask
) != 0) {
927 Status
= EFI_NOT_FOUND
;
932 // Search for the list of descriptors that cover the range BaseAddress to BaseAddress+Length
934 Status
= CoreSearchGcdMapEntry (*BaseAddress
, Length
, &StartLink
, &EndLink
, Map
);
935 if (EFI_ERROR (Status
)) {
936 Status
= EFI_NOT_FOUND
;
941 // Verify that the list of descriptors are unallocated memory matching GcdMemoryType.
944 while (Link
!= EndLink
->ForwardLink
) {
945 Entry
= CR (Link
, EFI_GCD_MAP_ENTRY
, Link
, EFI_GCD_MAP_SIGNATURE
);
946 Link
= Link
->ForwardLink
;
947 Status
= CoreAllocateSpaceCheckEntry (Operation
, Entry
, GcdMemoryType
, GcdIoType
);
948 if (EFI_ERROR (Status
)) {
955 Entry
= CR (Map
->BackLink
, EFI_GCD_MAP_ENTRY
, Link
, EFI_GCD_MAP_SIGNATURE
);
958 // Compute the maximum address to use in the search algorithm
960 if (GcdAllocateType
== EfiGcdAllocateMaxAddressSearchBottomUp
||
961 GcdAllocateType
== EfiGcdAllocateMaxAddressSearchTopDown
) {
962 MaxAddress
= *BaseAddress
;
964 MaxAddress
= Entry
->EndAddress
;
968 // Verify that the list of descriptors are unallocated memory matching GcdMemoryType.
970 if (GcdAllocateType
== EfiGcdAllocateMaxAddressSearchTopDown
||
971 GcdAllocateType
== EfiGcdAllocateAnySearchTopDown
) {
972 Link
= Map
->BackLink
;
974 Link
= Map
->ForwardLink
;
976 while (Link
!= Map
) {
977 Entry
= CR (Link
, EFI_GCD_MAP_ENTRY
, Link
, EFI_GCD_MAP_SIGNATURE
);
979 if (GcdAllocateType
== EfiGcdAllocateMaxAddressSearchTopDown
||
980 GcdAllocateType
== EfiGcdAllocateAnySearchTopDown
) {
981 Link
= Link
->BackLink
;
983 Link
= Link
->ForwardLink
;
986 Status
= CoreAllocateSpaceCheckEntry (Operation
, Entry
, GcdMemoryType
, GcdIoType
);
987 if (EFI_ERROR (Status
)) {
991 if (GcdAllocateType
== EfiGcdAllocateMaxAddressSearchTopDown
||
992 GcdAllocateType
== EfiGcdAllocateAnySearchTopDown
) {
993 if ((Entry
->BaseAddress
+ Length
) > MaxAddress
) {
996 if (Length
> (Entry
->EndAddress
+ 1)) {
997 Status
= EFI_NOT_FOUND
;
1000 if (Entry
->EndAddress
> MaxAddress
) {
1001 *BaseAddress
= MaxAddress
;
1003 *BaseAddress
= Entry
->EndAddress
;
1005 *BaseAddress
= (*BaseAddress
+ 1 - Length
) & (~AlignmentMask
);
1007 *BaseAddress
= (Entry
->BaseAddress
+ AlignmentMask
) & (~AlignmentMask
);
1008 if ((*BaseAddress
+ Length
- 1) > MaxAddress
) {
1009 Status
= EFI_NOT_FOUND
;
1015 // Search for the list of descriptors that cover the range BaseAddress to BaseAddress+Length
1017 Status
= CoreSearchGcdMapEntry (*BaseAddress
, Length
, &StartLink
, &EndLink
, Map
);
1018 if (EFI_ERROR (Status
)) {
1019 Status
= EFI_NOT_FOUND
;
1025 // Verify that the list of descriptors are unallocated memory matching GcdMemoryType.
1028 SubLink
= StartLink
;
1029 while (SubLink
!= EndLink
->ForwardLink
) {
1030 Entry
= CR (SubLink
, EFI_GCD_MAP_ENTRY
, Link
, EFI_GCD_MAP_SIGNATURE
);
1031 Status
= CoreAllocateSpaceCheckEntry (Operation
, Entry
, GcdMemoryType
, GcdIoType
);
1032 if (EFI_ERROR (Status
)) {
1037 SubLink
= SubLink
->ForwardLink
;
1045 Status
= EFI_NOT_FOUND
;
1050 // Allocate work space to perform this operation
1052 Status
= CoreAllocateGcdMapEntry (&TopEntry
, &BottomEntry
);
1053 if (EFI_ERROR (Status
)) {
1054 Status
= EFI_OUT_OF_RESOURCES
;
1059 // Convert/Insert the list of descriptors from StartLink to EndLink
1062 while (Link
!= EndLink
->ForwardLink
) {
1063 Entry
= CR (Link
, EFI_GCD_MAP_ENTRY
, Link
, EFI_GCD_MAP_SIGNATURE
);
1064 CoreInsertGcdMapEntry (Link
, Entry
, *BaseAddress
, Length
, TopEntry
, BottomEntry
);
1065 Entry
->ImageHandle
= ImageHandle
;
1066 Entry
->DeviceHandle
= DeviceHandle
;
1067 Link
= Link
->ForwardLink
;
1073 Status
= CoreCleanupGcdMapEntry (TopEntry
, BottomEntry
, StartLink
, EndLink
, Map
);
1076 if (Operation
& GCD_MEMORY_SPACE_OPERATION
) {
1077 CoreReleaseGcdMemoryLock ();
1079 if (Operation
& GCD_IO_SPACE_OPERATION
) {
1080 CoreReleaseGcdIoLock ();
1088 Add a segment of memory to GCD map.
1090 @param GcdMemoryType Memory type of the segment.
1091 @param BaseAddress Base address of the segment.
1092 @param Length Length of the segment.
1093 @param Capabilities alterable attributes of the segment.
1095 @retval EFI_INVALID_PARAMETER Invalid parameters.
1096 @retval EFI_SUCCESS Successfully add a segment of memory space.
1101 CoreInternalAddMemorySpace (
1102 IN EFI_GCD_MEMORY_TYPE GcdMemoryType
,
1103 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
1105 IN UINT64 Capabilities
1109 // Make sure parameters are valid
1111 if (GcdMemoryType
<= EfiGcdMemoryTypeNonExistent
|| GcdMemoryType
>= EfiGcdMemoryTypeMaximum
) {
1112 return EFI_INVALID_PARAMETER
;
1115 return CoreConvertSpace (GCD_ADD_MEMORY_OPERATION
, GcdMemoryType
, (EFI_GCD_IO_TYPE
) 0, BaseAddress
, Length
, Capabilities
, 0);
1119 // GCD Core Services
1123 Allocates nonexistent memory, reserved memory, system memory, or memorymapped
1124 I/O resources from the global coherency domain of the processor.
1126 @param GcdAllocateType The type of allocate operation
1127 @param GcdMemoryType The desired memory type
1128 @param Alignment Align with 2^Alignment
1129 @param Length Length to allocate
1130 @param BaseAddress Base address to allocate
1131 @param ImageHandle The image handle consume the allocated space.
1132 @param DeviceHandle The device handle consume the allocated space.
1134 @retval EFI_INVALID_PARAMETER Invalid parameter.
1135 @retval EFI_NOT_FOUND No descriptor contains the desired space.
1136 @retval EFI_SUCCESS Memory space successfully allocated.
1140 CoreAllocateMemorySpace (
1141 IN EFI_GCD_ALLOCATE_TYPE GcdAllocateType
,
1142 IN EFI_GCD_MEMORY_TYPE GcdMemoryType
,
1145 IN OUT EFI_PHYSICAL_ADDRESS
*BaseAddress
,
1146 IN EFI_HANDLE ImageHandle
,
1147 IN EFI_HANDLE DeviceHandle OPTIONAL
1150 return CoreAllocateSpace (
1151 GCD_ALLOCATE_MEMORY_OPERATION
,
1154 (EFI_GCD_IO_TYPE
) 0,
1165 Adds reserved memory, system memory, or memory-mapped I/O resources to the
1166 global coherency domain of the processor.
1168 @param GcdMemoryType Memory type of the memory space.
1169 @param BaseAddress Base address of the memory space.
1170 @param Length Length of the memory space.
1171 @param Capabilities alterable attributes of the memory space.
1173 @retval EFI_SUCCESS Merged this memory space into GCD map.
1177 CoreAddMemorySpace (
1178 IN EFI_GCD_MEMORY_TYPE GcdMemoryType
,
1179 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
1181 IN UINT64 Capabilities
1185 EFI_PHYSICAL_ADDRESS PageBaseAddress
;
1188 Status
= CoreInternalAddMemorySpace (GcdMemoryType
, BaseAddress
, Length
, Capabilities
);
1190 if (!EFI_ERROR (Status
) && GcdMemoryType
== EfiGcdMemoryTypeSystemMemory
) {
1192 PageBaseAddress
= PageAlignLength (BaseAddress
);
1193 PageLength
= PageAlignLength (BaseAddress
+ Length
- PageBaseAddress
);
1195 Status
= CoreAllocateMemorySpace (
1196 EfiGcdAllocateAddress
,
1201 gDxeCoreImageHandle
,
1205 if (!EFI_ERROR (Status
)) {
1206 CoreAddMemoryDescriptor (
1207 EfiConventionalMemory
,
1209 RShiftU64 (PageLength
, EFI_PAGE_SHIFT
),
1213 for (; PageLength
!= 0; PageLength
-= EFI_PAGE_SIZE
, PageBaseAddress
+= EFI_PAGE_SIZE
) {
1214 Status
= CoreAllocateMemorySpace (
1215 EfiGcdAllocateAddress
,
1220 gDxeCoreImageHandle
,
1224 if (!EFI_ERROR (Status
)) {
1225 CoreAddMemoryDescriptor (
1226 EfiConventionalMemory
,
1240 Frees nonexistent memory, reserved memory, system memory, or memory-mapped
1241 I/O resources from the global coherency domain of the processor.
1243 @param BaseAddress Base address of the memory space.
1244 @param Length Length of the memory space.
1246 @retval EFI_SUCCESS Space successfully freed.
1250 CoreFreeMemorySpace (
1251 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
1255 return CoreConvertSpace (GCD_FREE_MEMORY_OPERATION
, (EFI_GCD_MEMORY_TYPE
) 0, (EFI_GCD_IO_TYPE
) 0, BaseAddress
, Length
, 0, 0);
1260 Removes reserved memory, system memory, or memory-mapped I/O resources from
1261 the global coherency domain of the processor.
1263 @param BaseAddress Base address of the memory space.
1264 @param Length Length of the memory space.
1266 @retval EFI_SUCCESS Successfully remove a segment of memory space.
1270 CoreRemoveMemorySpace (
1271 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
1275 return CoreConvertSpace (GCD_REMOVE_MEMORY_OPERATION
, (EFI_GCD_MEMORY_TYPE
) 0, (EFI_GCD_IO_TYPE
) 0, BaseAddress
, Length
, 0, 0);
1280 Build a memory descriptor according to an entry.
1282 @param Descriptor The descriptor to be built
1283 @param Entry According to this entry
1288 BuildMemoryDescriptor (
1289 IN OUT EFI_GCD_MEMORY_SPACE_DESCRIPTOR
*Descriptor
,
1290 IN EFI_GCD_MAP_ENTRY
*Entry
1293 Descriptor
->BaseAddress
= Entry
->BaseAddress
;
1294 Descriptor
->Length
= Entry
->EndAddress
- Entry
->BaseAddress
+ 1;
1295 Descriptor
->Capabilities
= Entry
->Capabilities
;
1296 Descriptor
->Attributes
= Entry
->Attributes
;
1297 Descriptor
->GcdMemoryType
= Entry
->GcdMemoryType
;
1298 Descriptor
->ImageHandle
= Entry
->ImageHandle
;
1299 Descriptor
->DeviceHandle
= Entry
->DeviceHandle
;
1304 Retrieves the descriptor for a memory region containing a specified address.
1306 @param BaseAddress Specified start address
1307 @param Descriptor Specified length
1309 @retval EFI_INVALID_PARAMETER Invalid parameter
1310 @retval EFI_SUCCESS Successfully get memory space descriptor.
1314 CoreGetMemorySpaceDescriptor (
1315 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
1316 OUT EFI_GCD_MEMORY_SPACE_DESCRIPTOR
*Descriptor
1320 LIST_ENTRY
*StartLink
;
1321 LIST_ENTRY
*EndLink
;
1322 EFI_GCD_MAP_ENTRY
*Entry
;
1325 // Make sure parameters are valid
1327 if (Descriptor
== NULL
) {
1328 return EFI_INVALID_PARAMETER
;
1331 CoreAcquireGcdMemoryLock ();
1334 // Search for the list of descriptors that contain BaseAddress
1336 Status
= CoreSearchGcdMapEntry (BaseAddress
, 1, &StartLink
, &EndLink
, &mGcdMemorySpaceMap
);
1337 if (EFI_ERROR (Status
)) {
1338 Status
= EFI_NOT_FOUND
;
1341 // Copy the contents of the found descriptor into Descriptor
1343 Entry
= CR (StartLink
, EFI_GCD_MAP_ENTRY
, Link
, EFI_GCD_MAP_SIGNATURE
);
1344 BuildMemoryDescriptor (Descriptor
, Entry
);
1347 CoreReleaseGcdMemoryLock ();
1354 Modifies the attributes for a memory region in the global coherency domain of the
1357 @param BaseAddress Specified start address
1358 @param Length Specified length
1359 @param Attributes Specified attributes
1361 @retval EFI_SUCCESS Successfully set attribute of a segment of
1366 CoreSetMemorySpaceAttributes (
1367 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
1369 IN UINT64 Attributes
1372 return CoreConvertSpace (GCD_SET_ATTRIBUTES_MEMORY_OPERATION
, (EFI_GCD_MEMORY_TYPE
) 0, (EFI_GCD_IO_TYPE
) 0, BaseAddress
, Length
, 0, Attributes
);
1377 Returns a map of the memory resources in the global coherency domain of the
1380 @param NumberOfDescriptors Number of descriptors.
1381 @param MemorySpaceMap Descriptor array
1383 @retval EFI_INVALID_PARAMETER Invalid parameter
1384 @retval EFI_OUT_OF_RESOURCES No enough buffer to allocate
1385 @retval EFI_SUCCESS Successfully get memory space map.
1389 CoreGetMemorySpaceMap (
1390 OUT UINTN
*NumberOfDescriptors
,
1391 OUT EFI_GCD_MEMORY_SPACE_DESCRIPTOR
**MemorySpaceMap
1396 EFI_GCD_MAP_ENTRY
*Entry
;
1397 EFI_GCD_MEMORY_SPACE_DESCRIPTOR
*Descriptor
;
1400 // Make sure parameters are valid
1402 if (NumberOfDescriptors
== NULL
) {
1403 return EFI_INVALID_PARAMETER
;
1405 if (MemorySpaceMap
== NULL
) {
1406 return EFI_INVALID_PARAMETER
;
1409 CoreAcquireGcdMemoryLock ();
1412 // Count the number of descriptors
1414 *NumberOfDescriptors
= CoreCountGcdMapEntry (&mGcdMemorySpaceMap
);
1417 // Allocate the MemorySpaceMap
1419 *MemorySpaceMap
= CoreAllocateBootServicesPool (*NumberOfDescriptors
* sizeof (EFI_GCD_MEMORY_SPACE_DESCRIPTOR
));
1420 if (*MemorySpaceMap
== NULL
) {
1421 Status
= EFI_OUT_OF_RESOURCES
;
1426 // Fill in the MemorySpaceMap
1428 Descriptor
= *MemorySpaceMap
;
1429 Link
= mGcdMemorySpaceMap
.ForwardLink
;
1430 while (Link
!= &mGcdMemorySpaceMap
) {
1431 Entry
= CR (Link
, EFI_GCD_MAP_ENTRY
, Link
, EFI_GCD_MAP_SIGNATURE
);
1432 BuildMemoryDescriptor (Descriptor
, Entry
);
1434 Link
= Link
->ForwardLink
;
1436 Status
= EFI_SUCCESS
;
1439 CoreReleaseGcdMemoryLock ();
1445 Adds reserved I/O or I/O resources to the global coherency domain of the processor.
1447 @param GcdIoType IO type of the segment.
1448 @param BaseAddress Base address of the segment.
1449 @param Length Length of the segment.
1451 @retval EFI_SUCCESS Merged this segment into GCD map.
1452 @retval EFI_INVALID_PARAMETER Parameter not valid
1457 IN EFI_GCD_IO_TYPE GcdIoType
,
1458 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
1463 // Make sure parameters are valid
1465 if (GcdIoType
<= EfiGcdIoTypeNonExistent
|| GcdIoType
>= EfiGcdIoTypeMaximum
) {
1466 return EFI_INVALID_PARAMETER
;
1468 return CoreConvertSpace (GCD_ADD_IO_OPERATION
, (EFI_GCD_MEMORY_TYPE
) 0, GcdIoType
, BaseAddress
, Length
, 0, 0);
1473 Allocates nonexistent I/O, reserved I/O, or I/O resources from the global coherency
1474 domain of the processor.
1476 @param GcdAllocateType The type of allocate operation
1477 @param GcdIoType The desired IO type
1478 @param Alignment Align with 2^Alignment
1479 @param Length Length to allocate
1480 @param BaseAddress Base address to allocate
1481 @param ImageHandle The image handle consume the allocated space.
1482 @param DeviceHandle The device handle consume the allocated space.
1484 @retval EFI_INVALID_PARAMETER Invalid parameter.
1485 @retval EFI_NOT_FOUND No descriptor contains the desired space.
1486 @retval EFI_SUCCESS IO space successfully allocated.
1490 CoreAllocateIoSpace (
1491 IN EFI_GCD_ALLOCATE_TYPE GcdAllocateType
,
1492 IN EFI_GCD_IO_TYPE GcdIoType
,
1495 IN OUT EFI_PHYSICAL_ADDRESS
*BaseAddress
,
1496 IN EFI_HANDLE ImageHandle
,
1497 IN EFI_HANDLE DeviceHandle OPTIONAL
1500 return CoreAllocateSpace (
1501 GCD_ALLOCATE_IO_OPERATION
,
1503 (EFI_GCD_MEMORY_TYPE
) 0,
1515 Frees nonexistent I/O, reserved I/O, or I/O resources from the global coherency
1516 domain of the processor.
1518 @param BaseAddress Base address of the segment.
1519 @param Length Length of the segment.
1521 @retval EFI_SUCCESS Space successfully freed.
1526 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
1530 return CoreConvertSpace (GCD_FREE_IO_OPERATION
, (EFI_GCD_MEMORY_TYPE
) 0, (EFI_GCD_IO_TYPE
) 0, BaseAddress
, Length
, 0, 0);
1535 Removes reserved I/O or I/O resources from the global coherency domain of the
1538 @param BaseAddress Base address of the segment.
1539 @param Length Length of the segment.
1541 @retval EFI_SUCCESS Successfully removed a segment of IO space.
1546 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
1550 return CoreConvertSpace (GCD_REMOVE_IO_OPERATION
, (EFI_GCD_MEMORY_TYPE
) 0, (EFI_GCD_IO_TYPE
) 0, BaseAddress
, Length
, 0, 0);
1555 Build a IO descriptor according to an entry.
1557 @param Descriptor The descriptor to be built
1558 @param Entry According to this entry
1564 IN EFI_GCD_IO_SPACE_DESCRIPTOR
*Descriptor
,
1565 IN EFI_GCD_MAP_ENTRY
*Entry
1568 Descriptor
->BaseAddress
= Entry
->BaseAddress
;
1569 Descriptor
->Length
= Entry
->EndAddress
- Entry
->BaseAddress
+ 1;
1570 Descriptor
->GcdIoType
= Entry
->GcdIoType
;
1571 Descriptor
->ImageHandle
= Entry
->ImageHandle
;
1572 Descriptor
->DeviceHandle
= Entry
->DeviceHandle
;
1577 Retrieves the descriptor for an I/O region containing a specified address.
1579 @param BaseAddress Specified start address
1580 @param Descriptor Specified length
1582 @retval EFI_INVALID_PARAMETER Descriptor is NULL.
1583 @retval EFI_SUCCESS Successfully get the IO space descriptor.
1587 CoreGetIoSpaceDescriptor (
1588 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
1589 OUT EFI_GCD_IO_SPACE_DESCRIPTOR
*Descriptor
1593 LIST_ENTRY
*StartLink
;
1594 LIST_ENTRY
*EndLink
;
1595 EFI_GCD_MAP_ENTRY
*Entry
;
1598 // Make sure parameters are valid
1600 if (Descriptor
== NULL
) {
1601 return EFI_INVALID_PARAMETER
;
1604 CoreAcquireGcdIoLock ();
1607 // Search for the list of descriptors that contain BaseAddress
1609 Status
= CoreSearchGcdMapEntry (BaseAddress
, 1, &StartLink
, &EndLink
, &mGcdIoSpaceMap
);
1610 if (EFI_ERROR (Status
)) {
1611 Status
= EFI_NOT_FOUND
;
1614 // Copy the contents of the found descriptor into Descriptor
1616 Entry
= CR (StartLink
, EFI_GCD_MAP_ENTRY
, Link
, EFI_GCD_MAP_SIGNATURE
);
1617 BuildIoDescriptor (Descriptor
, Entry
);
1620 CoreReleaseGcdIoLock ();
1627 Returns a map of the I/O resources in the global coherency domain of the processor.
1629 @param NumberOfDescriptors Number of descriptors.
1630 @param IoSpaceMap Descriptor array
1632 @retval EFI_INVALID_PARAMETER Invalid parameter
1633 @retval EFI_OUT_OF_RESOURCES No enough buffer to allocate
1634 @retval EFI_SUCCESS Successfully get IO space map.
1639 OUT UINTN
*NumberOfDescriptors
,
1640 OUT EFI_GCD_IO_SPACE_DESCRIPTOR
**IoSpaceMap
1645 EFI_GCD_MAP_ENTRY
*Entry
;
1646 EFI_GCD_IO_SPACE_DESCRIPTOR
*Descriptor
;
1649 // Make sure parameters are valid
1651 if (NumberOfDescriptors
== NULL
) {
1652 return EFI_INVALID_PARAMETER
;
1654 if (IoSpaceMap
== NULL
) {
1655 return EFI_INVALID_PARAMETER
;
1658 CoreAcquireGcdIoLock ();
1661 // Count the number of descriptors
1663 *NumberOfDescriptors
= CoreCountGcdMapEntry (&mGcdIoSpaceMap
);
1666 // Allocate the IoSpaceMap
1668 *IoSpaceMap
= CoreAllocateBootServicesPool (*NumberOfDescriptors
* sizeof (EFI_GCD_IO_SPACE_DESCRIPTOR
));
1669 if (*IoSpaceMap
== NULL
) {
1670 Status
= EFI_OUT_OF_RESOURCES
;
1675 // Fill in the IoSpaceMap
1677 Descriptor
= *IoSpaceMap
;
1678 Link
= mGcdIoSpaceMap
.ForwardLink
;
1679 while (Link
!= &mGcdIoSpaceMap
) {
1680 Entry
= CR (Link
, EFI_GCD_MAP_ENTRY
, Link
, EFI_GCD_MAP_SIGNATURE
);
1681 BuildIoDescriptor (Descriptor
, Entry
);
1683 Link
= Link
->ForwardLink
;
1685 Status
= EFI_SUCCESS
;
1688 CoreReleaseGcdIoLock ();
1694 Converts a Resource Descriptor HOB attributes mask to an EFI Memory Descriptor
1697 @param GcdMemoryType Type of resource in the GCD memory map.
1698 @param Attributes The attribute mask in the Resource Descriptor
1701 @return The capabilities mask for an EFI Memory Descriptor.
1706 CoreConvertResourceDescriptorHobAttributesToCapabilities (
1707 EFI_GCD_MEMORY_TYPE GcdMemoryType
,
1711 UINT64 Capabilities
;
1712 GCD_ATTRIBUTE_CONVERSION_ENTRY
*Conversion
;
1715 // Convert the Resource HOB Attributes to an EFI Memory Capabilities mask
1717 for (Capabilities
= 0, Conversion
= mAttributeConversionTable
; Conversion
->Attribute
!= 0; Conversion
++) {
1718 if (Conversion
->Memory
|| (GcdMemoryType
!= EfiGcdMemoryTypeSystemMemory
)) {
1719 if (Attributes
& Conversion
->Attribute
) {
1720 Capabilities
|= Conversion
->Capability
;
1725 return Capabilities
;
1730 External function. Initializes the GCD and memory services based on the memory
1731 descriptor HOBs. This function is responsible for priming the GCD map and the
1732 memory map, so memory allocations and resource allocations can be made. The first
1733 part of this function can not depend on any memory services until at least one
1734 memory descriptor is provided to the memory services. Then the memory services
1735 can be used to intialize the GCD map.
1737 @param HobStart The start address of the HOB.
1738 @param MemoryBaseAddress Start address of memory region found to init DXE
1740 @param MemoryLength Length of memory region found to init DXE core.
1742 @retval EFI_SUCCESS Memory services successfully initialized.
1746 CoreInitializeMemoryServices (
1748 OUT EFI_PHYSICAL_ADDRESS
*MemoryBaseAddress
,
1749 OUT UINT64
*MemoryLength
1752 EFI_PEI_HOB_POINTERS Hob
;
1753 EFI_MEMORY_TYPE_INFORMATION
*EfiMemoryTypeInformation
;
1756 EFI_HOB_HANDOFF_INFO_TABLE
*PhitHob
;
1757 EFI_HOB_RESOURCE_DESCRIPTOR
*ResourceHob
;
1758 EFI_HOB_RESOURCE_DESCRIPTOR
*PhitResourceHob
;
1759 EFI_PHYSICAL_ADDRESS BaseAddress
;
1762 UINT64 Capabilities
;
1763 EFI_PHYSICAL_ADDRESS MaxMemoryBaseAddress
;
1764 UINT64 MaxMemoryLength
;
1765 UINT64 MaxMemoryAttributes
;
1766 EFI_PHYSICAL_ADDRESS MaxAddress
;
1767 EFI_PHYSICAL_ADDRESS HighAddress
;
1768 EFI_HOB_RESOURCE_DESCRIPTOR
*MaxResourceHob
;
1769 EFI_HOB_GUID_TYPE
*GuidHob
;
1772 // Point at the first HOB. This must be the PHIT HOB.
1774 Hob
.Raw
= *HobStart
;
1775 ASSERT (GET_HOB_TYPE (Hob
) == EFI_HOB_TYPE_HANDOFF
);
1778 // Initialize the spin locks and maps in the memory services.
1779 // Also fill in the memory services into the EFI Boot Services Table
1781 CoreInitializePool ();
1784 // Initialize Local Variables
1786 PhitResourceHob
= NULL
;
1787 MaxResourceHob
= NULL
;
1792 MaxMemoryBaseAddress
= 0;
1793 MaxMemoryLength
= 0;
1794 MaxMemoryAttributes
= 0;
1797 // Cache the PHIT HOB for later use
1799 PhitHob
= Hob
.HandoffInformationTable
;
1802 // See if a Memory Type Information HOB is available
1804 GuidHob
= GetFirstGuidHob (&gEfiMemoryTypeInformationGuid
);
1805 if (GuidHob
!= NULL
) {
1806 EfiMemoryTypeInformation
= GET_GUID_HOB_DATA (GuidHob
);
1807 DataSize
= GET_GUID_HOB_DATA_SIZE (GuidHob
);
1808 if (EfiMemoryTypeInformation
!= NULL
&& DataSize
> 0 && DataSize
<= (EfiMaxMemoryType
+ 1) * sizeof (EFI_MEMORY_TYPE_INFORMATION
)) {
1809 CopyMem (&gMemoryTypeInformation
, EfiMemoryTypeInformation
, DataSize
);
1814 // Find the Resource Descriptor HOB that contains range FreeMemoryBaseAddress..FreeMemoryLength
1818 for (Hob
.Raw
= *HobStart
; !END_OF_HOB_LIST(Hob
); Hob
.Raw
= GET_NEXT_HOB(Hob
)) {
1820 if (GET_HOB_TYPE (Hob
) == EFI_HOB_TYPE_RESOURCE_DESCRIPTOR
) {
1822 ResourceHob
= Hob
.ResourceDescriptor
;
1824 if (ResourceHob
->ResourceType
== EFI_RESOURCE_SYSTEM_MEMORY
&&
1825 (ResourceHob
->ResourceAttribute
& MEMORY_ATTRIBUTE_MASK
) == TESTED_MEMORY_ATTRIBUTES
) {
1827 if (PhitHob
->EfiFreeMemoryBottom
>= ResourceHob
->PhysicalStart
&&
1828 PhitHob
->EfiFreeMemoryTop
<= (ResourceHob
->PhysicalStart
+ ResourceHob
->ResourceLength
) ) {
1831 // Cache the resource descriptor HOB for the memory region described by the PHIT HOB
1833 PhitResourceHob
= ResourceHob
;
1836 Attributes
= PhitResourceHob
->ResourceAttribute
;
1837 BaseAddress
= PageAlignAddress (PhitHob
->EfiMemoryTop
);
1838 Length
= PageAlignLength (ResourceHob
->PhysicalStart
+ ResourceHob
->ResourceLength
- BaseAddress
);
1839 if (Length
< MINIMUM_INITIAL_MEMORY_SIZE
) {
1840 BaseAddress
= PageAlignAddress (PhitHob
->EfiFreeMemoryBottom
);
1841 Length
= PageAlignLength (PhitHob
->EfiFreeMemoryTop
- BaseAddress
);
1842 if (Length
< MINIMUM_INITIAL_MEMORY_SIZE
) {
1843 BaseAddress
= PageAlignAddress (ResourceHob
->PhysicalStart
);
1844 Length
= PageAlignLength ((UINT64
)((UINTN
)*HobStart
- BaseAddress
));
1854 // Assert if a resource descriptor HOB for the memory region described by the PHIT was not found
1859 // Search all the resource descriptor HOBs from the highest possible addresses down for a memory
1860 // region that is big enough to initialize the DXE core. Always skip the PHIT Resource HOB.
1861 // The max address must be within the physically addressible range for the processor.
1863 MaxMemoryLength
= 0;
1864 MaxAddress
= EFI_MAX_ADDRESS
;
1869 // Search for a tested memory region that is below MaxAddress
1871 for (Hob
.Raw
= *HobStart
; !END_OF_HOB_LIST(Hob
); Hob
.Raw
= GET_NEXT_HOB(Hob
)) {
1874 // See if this is a resource descriptor HOB that does not contain the PHIT.
1876 if (Hob
.ResourceDescriptor
!= PhitResourceHob
&& GET_HOB_TYPE (Hob
) == EFI_HOB_TYPE_RESOURCE_DESCRIPTOR
) {
1878 ResourceHob
= Hob
.ResourceDescriptor
;
1880 // See if this resource descrior HOB describes tested system memory below MaxAddress
1882 if (ResourceHob
->ResourceType
== EFI_RESOURCE_SYSTEM_MEMORY
&&
1883 (ResourceHob
->ResourceAttribute
& MEMORY_ATTRIBUTE_MASK
) == TESTED_MEMORY_ATTRIBUTES
&&
1884 ResourceHob
->PhysicalStart
+ ResourceHob
->ResourceLength
<= MaxAddress
) {
1887 // See if this is the highest tested system memory region below MaxAddress
1889 if (ResourceHob
->PhysicalStart
> HighAddress
) {
1891 MaxResourceHob
= ResourceHob
;
1892 HighAddress
= MaxResourceHob
->PhysicalStart
;
1900 // Compute the size of the tested memory region below MaxAddrees
1902 MaxMemoryBaseAddress
= PageAlignAddress (MaxResourceHob
->PhysicalStart
);
1903 MaxMemoryLength
= PageAlignLength (MaxResourceHob
->PhysicalStart
+ MaxResourceHob
->ResourceLength
- MaxMemoryBaseAddress
);
1904 MaxMemoryAttributes
= MaxResourceHob
->ResourceAttribute
;
1906 MaxAddress
= ResourceHob
->PhysicalStart
;
1907 } while (Found
&& MaxMemoryLength
< MINIMUM_INITIAL_MEMORY_SIZE
);
1912 if ((Length
< MINIMUM_INITIAL_MEMORY_SIZE
) ||
1913 (MaxMemoryBaseAddress
> BaseAddress
&& MaxMemoryLength
>= MINIMUM_INITIAL_MEMORY_SIZE
) ) {
1914 BaseAddress
= MaxMemoryBaseAddress
;
1915 Length
= MaxMemoryLength
;
1916 Attributes
= MaxMemoryAttributes
;
1920 // If no memory regions are found that are big enough to initialize the DXE core, then ASSERT().
1922 ASSERT (Length
>= MINIMUM_INITIAL_MEMORY_SIZE
);
1925 // Convert the Resource HOB Attributes to an EFI Memory Capabilities mask
1927 Capabilities
= CoreConvertResourceDescriptorHobAttributesToCapabilities (EfiGcdMemoryTypeSystemMemory
, Attributes
);
1930 // Declare the very first memory region, so the EFI Memory Services are available.
1932 CoreAddMemoryDescriptor (
1933 EfiConventionalMemory
,
1935 RShiftU64 (Length
, EFI_PAGE_SHIFT
),
1939 *MemoryBaseAddress
= BaseAddress
;
1940 *MemoryLength
= Length
;
1947 External function. Initializes the GCD and memory services based on the memory
1948 descriptor HOBs. This function is responsible for priming the GCD map and the
1949 memory map, so memory allocations and resource allocations can be made. The first
1950 part of this function can not depend on any memory services until at least one
1951 memory descriptor is provided to the memory services. Then the memory services
1952 can be used to intialize the GCD map. The HobStart will be relocated to a pool
1955 @param HobStart The start address of the HOB
1956 @param MemoryBaseAddress Start address of memory region found to init DXE
1958 @param MemoryLength Length of memory region found to init DXE core.
1960 @retval EFI_SUCCESS GCD services successfully initialized.
1964 CoreInitializeGcdServices (
1965 IN OUT VOID
**HobStart
,
1966 IN EFI_PHYSICAL_ADDRESS MemoryBaseAddress
,
1967 IN UINT64 MemoryLength
1970 EFI_PEI_HOB_POINTERS Hob
;
1972 EFI_HOB_HANDOFF_INFO_TABLE
*PhitHob
;
1973 UINT8 SizeOfMemorySpace
;
1974 UINT8 SizeOfIoSpace
;
1975 EFI_HOB_RESOURCE_DESCRIPTOR
*ResourceHob
;
1976 EFI_PHYSICAL_ADDRESS BaseAddress
;
1979 EFI_GCD_MAP_ENTRY
*Entry
;
1980 EFI_GCD_MEMORY_TYPE GcdMemoryType
;
1981 EFI_GCD_IO_TYPE GcdIoType
;
1982 EFI_GCD_MEMORY_SPACE_DESCRIPTOR Descriptor
;
1983 EFI_HOB_MEMORY_ALLOCATION
*MemoryHob
;
1984 EFI_HOB_FIRMWARE_VOLUME
*FirmwareVolumeHob
;
1985 UINTN NumberOfDescriptors
;
1986 EFI_GCD_MEMORY_SPACE_DESCRIPTOR
*MemorySpaceMap
;
1988 UINT64 Capabilities
;
1989 EFI_HOB_CPU
* CpuHob
;
1991 // Cache the PHIT HOB for later use
1993 PhitHob
= (EFI_HOB_HANDOFF_INFO_TABLE
*)(*HobStart
);
1996 // Get the number of address lines in the I/O and Memory space for the CPU
1998 CpuHob
= GetFirstHob (EFI_HOB_TYPE_CPU
);
1999 ASSERT (CpuHob
!= NULL
);
2000 SizeOfMemorySpace
= CpuHob
->SizeOfMemorySpace
;
2001 SizeOfIoSpace
= CpuHob
->SizeOfIoSpace
;
2004 // Initialize the GCD Memory Space Map
2006 Entry
= CoreAllocateCopyPool (sizeof (EFI_GCD_MAP_ENTRY
), &mGcdMemorySpaceMapEntryTemplate
);
2007 ASSERT (Entry
!= NULL
);
2009 Entry
->EndAddress
= LShiftU64 (1, SizeOfMemorySpace
) - 1;
2011 InsertHeadList (&mGcdMemorySpaceMap
, &Entry
->Link
);
2014 // Initialize the GCD I/O Space Map
2016 Entry
= CoreAllocateCopyPool (sizeof (EFI_GCD_MAP_ENTRY
), &mGcdIoSpaceMapEntryTemplate
);
2017 ASSERT (Entry
!= NULL
);
2019 Entry
->EndAddress
= LShiftU64 (1, SizeOfIoSpace
) - 1;
2021 InsertHeadList (&mGcdIoSpaceMap
, &Entry
->Link
);
2024 // Walk the HOB list and add all resource descriptors to the GCD
2026 for (Hob
.Raw
= *HobStart
; !END_OF_HOB_LIST(Hob
); Hob
.Raw
= GET_NEXT_HOB(Hob
)) {
2028 GcdMemoryType
= EfiGcdMemoryTypeNonExistent
;
2029 GcdIoType
= EfiGcdIoTypeNonExistent
;
2031 if (GET_HOB_TYPE (Hob
) == EFI_HOB_TYPE_RESOURCE_DESCRIPTOR
) {
2033 ResourceHob
= Hob
.ResourceDescriptor
;
2035 switch (ResourceHob
->ResourceType
) {
2036 case EFI_RESOURCE_SYSTEM_MEMORY
:
2037 if ((ResourceHob
->ResourceAttribute
& MEMORY_ATTRIBUTE_MASK
) == TESTED_MEMORY_ATTRIBUTES
) {
2038 GcdMemoryType
= EfiGcdMemoryTypeSystemMemory
;
2040 if ((ResourceHob
->ResourceAttribute
& MEMORY_ATTRIBUTE_MASK
) == INITIALIZED_MEMORY_ATTRIBUTES
) {
2041 GcdMemoryType
= EfiGcdMemoryTypeReserved
;
2043 if ((ResourceHob
->ResourceAttribute
& MEMORY_ATTRIBUTE_MASK
) == PRESENT_MEMORY_ATTRIBUTES
) {
2044 GcdMemoryType
= EfiGcdMemoryTypeReserved
;
2047 case EFI_RESOURCE_MEMORY_MAPPED_IO
:
2048 case EFI_RESOURCE_FIRMWARE_DEVICE
:
2049 GcdMemoryType
= EfiGcdMemoryTypeMemoryMappedIo
;
2051 case EFI_RESOURCE_MEMORY_MAPPED_IO_PORT
:
2052 case EFI_RESOURCE_MEMORY_RESERVED
:
2053 GcdMemoryType
= EfiGcdMemoryTypeReserved
;
2055 case EFI_RESOURCE_IO
:
2056 GcdIoType
= EfiGcdIoTypeIo
;
2058 case EFI_RESOURCE_IO_RESERVED
:
2059 GcdIoType
= EfiGcdIoTypeReserved
;
2063 if (GcdMemoryType
!= EfiGcdMemoryTypeNonExistent
) {
2066 // Convert the Resource HOB Attributes to an EFI Memory Capabilities mask
2068 Capabilities
= CoreConvertResourceDescriptorHobAttributesToCapabilities (
2070 ResourceHob
->ResourceAttribute
2073 Status
= CoreInternalAddMemorySpace (
2075 ResourceHob
->PhysicalStart
,
2076 ResourceHob
->ResourceLength
,
2081 if (GcdIoType
!= EfiGcdIoTypeNonExistent
) {
2082 Status
= CoreAddIoSpace (
2084 ResourceHob
->PhysicalStart
,
2085 ResourceHob
->ResourceLength
2092 // Allocate first memory region from the GCD by the DXE core
2094 Status
= CoreAllocateMemorySpace (
2095 EfiGcdAllocateAddress
,
2096 EfiGcdMemoryTypeSystemMemory
,
2100 gDxeCoreImageHandle
,
2105 // Walk the HOB list and allocate all memory space that is consumed by memory allocation HOBs,
2106 // and Firmware Volume HOBs. Also update the EFI Memory Map with the memory allocation HOBs.
2108 for (Hob
.Raw
= *HobStart
; !END_OF_HOB_LIST(Hob
); Hob
.Raw
= GET_NEXT_HOB(Hob
)) {
2109 if (GET_HOB_TYPE (Hob
) == EFI_HOB_TYPE_MEMORY_ALLOCATION
) {
2110 MemoryHob
= Hob
.MemoryAllocation
;
2111 BaseAddress
= MemoryHob
->AllocDescriptor
.MemoryBaseAddress
;
2112 Status
= CoreGetMemorySpaceDescriptor (BaseAddress
, &Descriptor
);
2113 if (!EFI_ERROR (Status
)) {
2114 Status
= CoreAllocateMemorySpace (
2115 EfiGcdAllocateAddress
,
2116 Descriptor
.GcdMemoryType
,
2118 MemoryHob
->AllocDescriptor
.MemoryLength
,
2120 gDxeCoreImageHandle
,
2123 if (!EFI_ERROR (Status
) && Descriptor
.GcdMemoryType
== EfiGcdMemoryTypeSystemMemory
) {
2124 CoreAddMemoryDescriptor (
2125 MemoryHob
->AllocDescriptor
.MemoryType
,
2126 MemoryHob
->AllocDescriptor
.MemoryBaseAddress
,
2127 RShiftU64 (MemoryHob
->AllocDescriptor
.MemoryLength
, EFI_PAGE_SHIFT
),
2128 Descriptor
.Capabilities
& (~EFI_MEMORY_RUNTIME
)
2134 if (GET_HOB_TYPE (Hob
) == EFI_HOB_TYPE_FV
) {
2135 FirmwareVolumeHob
= Hob
.FirmwareVolume
;
2136 BaseAddress
= FirmwareVolumeHob
->BaseAddress
;
2137 Status
= CoreAllocateMemorySpace (
2138 EfiGcdAllocateAddress
,
2139 EfiGcdMemoryTypeMemoryMappedIo
,
2141 FirmwareVolumeHob
->Length
,
2143 gDxeCoreImageHandle
,
2150 // Relocate HOB List to an allocated pool buffer.
2152 NewHobList
= CoreAllocateCopyPool (
2153 (UINTN
)PhitHob
->EfiFreeMemoryBottom
- (UINTN
)(*HobStart
),
2156 ASSERT (NewHobList
!= NULL
);
2158 *HobStart
= NewHobList
;
2159 gHobList
= NewHobList
;
2162 // Add and allocate the remaining unallocated system memory to the memory services.
2164 Status
= CoreGetMemorySpaceMap (&NumberOfDescriptors
, &MemorySpaceMap
);
2165 for (Index
= 0; Index
< NumberOfDescriptors
; Index
++) {
2166 if (MemorySpaceMap
[Index
].GcdMemoryType
== EfiGcdMemoryTypeSystemMemory
) {
2167 if (MemorySpaceMap
[Index
].ImageHandle
== NULL
) {
2168 BaseAddress
= PageAlignAddress (MemorySpaceMap
[Index
].BaseAddress
);
2169 Length
= PageAlignLength (MemorySpaceMap
[Index
].BaseAddress
+ MemorySpaceMap
[Index
].Length
- BaseAddress
);
2170 if (Length
== 0 || MemorySpaceMap
[Index
].BaseAddress
+ MemorySpaceMap
[Index
].Length
< BaseAddress
) {
2173 CoreAddMemoryDescriptor (
2174 EfiConventionalMemory
,
2176 RShiftU64 (Length
, EFI_PAGE_SHIFT
),
2177 MemorySpaceMap
[Index
].Capabilities
& (~EFI_MEMORY_RUNTIME
)
2179 Status
= CoreAllocateMemorySpace (
2180 EfiGcdAllocateAddress
,
2181 EfiGcdMemoryTypeSystemMemory
,
2185 gDxeCoreImageHandle
,
2191 CoreFreePool (MemorySpaceMap
);