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.
20 #define MINIMUM_INITIAL_MEMORY_SIZE 0x10000
22 #define MEMORY_ATTRIBUTE_MASK (EFI_RESOURCE_ATTRIBUTE_PRESENT | \
23 EFI_RESOURCE_ATTRIBUTE_INITIALIZED | \
24 EFI_RESOURCE_ATTRIBUTE_TESTED | \
25 EFI_RESOURCE_ATTRIBUTE_READ_PROTECTED | \
26 EFI_RESOURCE_ATTRIBUTE_WRITE_PROTECTED | \
27 EFI_RESOURCE_ATTRIBUTE_EXECUTION_PROTECTED | \
28 EFI_RESOURCE_ATTRIBUTE_16_BIT_IO | \
29 EFI_RESOURCE_ATTRIBUTE_32_BIT_IO | \
30 EFI_RESOURCE_ATTRIBUTE_64_BIT_IO )
32 #define TESTED_MEMORY_ATTRIBUTES (EFI_RESOURCE_ATTRIBUTE_PRESENT | \
33 EFI_RESOURCE_ATTRIBUTE_INITIALIZED | \
34 EFI_RESOURCE_ATTRIBUTE_TESTED )
36 #define INITIALIZED_MEMORY_ATTRIBUTES (EFI_RESOURCE_ATTRIBUTE_PRESENT | \
37 EFI_RESOURCE_ATTRIBUTE_INITIALIZED )
39 #define PRESENT_MEMORY_ATTRIBUTES (EFI_RESOURCE_ATTRIBUTE_PRESENT)
41 #define INVALID_CPU_ARCH_ATTRIBUTES 0xffffffff
46 EFI_LOCK mGcdMemorySpaceLock
= EFI_INITIALIZE_LOCK_VARIABLE (TPL_NOTIFY
);
47 EFI_LOCK mGcdIoSpaceLock
= EFI_INITIALIZE_LOCK_VARIABLE (TPL_NOTIFY
);
48 LIST_ENTRY mGcdMemorySpaceMap
= INITIALIZE_LIST_HEAD_VARIABLE (mGcdMemorySpaceMap
);
49 LIST_ENTRY mGcdIoSpaceMap
= INITIALIZE_LIST_HEAD_VARIABLE (mGcdIoSpaceMap
);
51 EFI_GCD_MAP_ENTRY mGcdMemorySpaceMapEntryTemplate
= {
52 EFI_GCD_MAP_SIGNATURE
,
61 EfiGcdMemoryTypeNonExistent
,
67 EFI_GCD_MAP_ENTRY mGcdIoSpaceMapEntryTemplate
= {
68 EFI_GCD_MAP_SIGNATURE
,
77 (EFI_GCD_MEMORY_TYPE
) 0,
78 EfiGcdIoTypeNonExistent
,
83 GCD_ATTRIBUTE_CONVERSION_ENTRY mAttributeConversionTable
[] = {
84 { EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE
, EFI_MEMORY_UC
, TRUE
},
85 { EFI_RESOURCE_ATTRIBUTE_UNCACHED_EXPORTED
, EFI_MEMORY_UCE
, TRUE
},
86 { EFI_RESOURCE_ATTRIBUTE_WRITE_COMBINEABLE
, EFI_MEMORY_WC
, TRUE
},
87 { EFI_RESOURCE_ATTRIBUTE_WRITE_THROUGH_CACHEABLE
, EFI_MEMORY_WT
, TRUE
},
88 { EFI_RESOURCE_ATTRIBUTE_WRITE_BACK_CACHEABLE
, EFI_MEMORY_WB
, TRUE
},
89 { EFI_RESOURCE_ATTRIBUTE_READ_PROTECTED
, EFI_MEMORY_RP
, TRUE
},
90 { EFI_RESOURCE_ATTRIBUTE_WRITE_PROTECTED
, EFI_MEMORY_WP
, TRUE
},
91 { EFI_RESOURCE_ATTRIBUTE_EXECUTION_PROTECTED
, EFI_MEMORY_XP
, TRUE
},
92 { EFI_RESOURCE_ATTRIBUTE_PRESENT
, EFI_MEMORY_PRESENT
, FALSE
},
93 { EFI_RESOURCE_ATTRIBUTE_INITIALIZED
, EFI_MEMORY_INITIALIZED
, FALSE
},
94 { EFI_RESOURCE_ATTRIBUTE_TESTED
, EFI_MEMORY_TESTED
, FALSE
},
100 Acquire memory lock on mGcdMemorySpaceLock.
104 CoreAcquireGcdMemoryLock (
108 CoreAcquireLock (&mGcdMemorySpaceLock
);
114 Release memory lock on mGcdMemorySpaceLock.
118 CoreReleaseGcdMemoryLock (
122 CoreReleaseLock (&mGcdMemorySpaceLock
);
128 Acquire memory lock on mGcdIoSpaceLock.
132 CoreAcquireGcdIoLock (
136 CoreAcquireLock (&mGcdIoSpaceLock
);
141 Release memory lock on mGcdIoSpaceLock.
145 CoreReleaseGcdIoLock (
149 CoreReleaseLock (&mGcdIoSpaceLock
);
155 // GCD Initialization Worker Functions
158 Aligns a value to the specified boundary.
160 @param Value 64 bit value to align
161 @param Alignment Log base 2 of the boundary to align Value to
162 @param RoundUp TRUE if Value is to be rounded up to the nearest
163 aligned boundary. FALSE is Value is to be
164 rounded down to the nearest aligned boundary.
166 @return A 64 bit value is the aligned to the value nearest Value with an alignment by Alignment.
176 UINT64 AlignmentMask
;
178 AlignmentMask
= LShiftU64 (1, Alignment
) - 1;
180 Value
+= AlignmentMask
;
182 return Value
& (~AlignmentMask
);
187 Aligns address to the page boundary.
189 @param Value 64 bit address to align
191 @return A 64 bit value is the aligned to the value nearest Value with an alignment by Alignment.
199 return AlignValue (Value
, EFI_PAGE_SHIFT
, TRUE
);
204 Aligns length to the page boundary.
206 @param Value 64 bit length to align
208 @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.
234 CoreAllocateGcdMapEntry (
235 IN OUT EFI_GCD_MAP_ENTRY
**TopEntry
,
236 IN OUT EFI_GCD_MAP_ENTRY
**BottomEntry
239 *TopEntry
= AllocateZeroPool (sizeof (EFI_GCD_MAP_ENTRY
));
240 if (*TopEntry
== NULL
) {
241 return EFI_OUT_OF_RESOURCES
;
244 *BottomEntry
= AllocateZeroPool (sizeof (EFI_GCD_MAP_ENTRY
));
245 if (*BottomEntry
== NULL
) {
246 CoreFreePool (*TopEntry
);
247 return EFI_OUT_OF_RESOURCES
;
255 Internal function. Inserts a new descriptor into a sorted list
257 @param Link The linked list to insert the range BaseAddress
259 @param Entry A pointer to the entry that is inserted
260 @param BaseAddress The base address of the new range
261 @param Length The length of the new range in bytes
262 @param TopEntry Top pad entry to insert if needed.
263 @param BottomEntry Bottom pad entry to insert if needed.
265 @retval EFI_SUCCESS The new range was inserted into the linked list
269 CoreInsertGcdMapEntry (
271 IN EFI_GCD_MAP_ENTRY
*Entry
,
272 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
274 IN EFI_GCD_MAP_ENTRY
*TopEntry
,
275 IN EFI_GCD_MAP_ENTRY
*BottomEntry
278 ASSERT (Length
!= 0);
279 ASSERT (TopEntry
->Signature
== 0);
280 ASSERT (BottomEntry
->Signature
== 0);
282 if (BaseAddress
> Entry
->BaseAddress
) {
283 CopyMem (BottomEntry
, Entry
, sizeof (EFI_GCD_MAP_ENTRY
));
284 Entry
->BaseAddress
= BaseAddress
;
285 BottomEntry
->EndAddress
= BaseAddress
- 1;
286 InsertTailList (Link
, &BottomEntry
->Link
);
289 if ((BaseAddress
+ Length
- 1) < Entry
->EndAddress
) {
290 CopyMem (TopEntry
, Entry
, sizeof (EFI_GCD_MAP_ENTRY
));
291 TopEntry
->BaseAddress
= BaseAddress
+ Length
;
292 Entry
->EndAddress
= BaseAddress
+ Length
- 1;
293 InsertHeadList (Link
, &TopEntry
->Link
);
301 Merge the Gcd region specified by Link and its adjacent entry.
303 @param Link Specify the entry to be merged (with its
305 @param Forward Direction (forward or backward).
308 @retval EFI_SUCCESS Successfully returned.
309 @retval EFI_UNSUPPORTED These adjacent regions could not merge.
313 CoreMergeGcdMapEntry (
319 LIST_ENTRY
*AdjacentLink
;
320 EFI_GCD_MAP_ENTRY
*Entry
;
321 EFI_GCD_MAP_ENTRY
*AdjacentEntry
;
324 // Get adjacent entry
327 AdjacentLink
= Link
->ForwardLink
;
329 AdjacentLink
= Link
->BackLink
;
333 // If AdjacentLink is the head of the list, then no merge can be performed
335 if (AdjacentLink
== Map
) {
339 Entry
= CR (Link
, EFI_GCD_MAP_ENTRY
, Link
, EFI_GCD_MAP_SIGNATURE
);
340 AdjacentEntry
= CR (AdjacentLink
, EFI_GCD_MAP_ENTRY
, Link
, EFI_GCD_MAP_SIGNATURE
);
342 if (Entry
->Capabilities
!= AdjacentEntry
->Capabilities
) {
343 return EFI_UNSUPPORTED
;
345 if (Entry
->Attributes
!= AdjacentEntry
->Attributes
) {
346 return EFI_UNSUPPORTED
;
348 if (Entry
->GcdMemoryType
!= AdjacentEntry
->GcdMemoryType
) {
349 return EFI_UNSUPPORTED
;
351 if (Entry
->GcdIoType
!= AdjacentEntry
->GcdIoType
) {
352 return EFI_UNSUPPORTED
;
354 if (Entry
->ImageHandle
!= AdjacentEntry
->ImageHandle
) {
355 return EFI_UNSUPPORTED
;
357 if (Entry
->DeviceHandle
!= AdjacentEntry
->DeviceHandle
) {
358 return EFI_UNSUPPORTED
;
362 Entry
->EndAddress
= AdjacentEntry
->EndAddress
;
364 Entry
->BaseAddress
= AdjacentEntry
->BaseAddress
;
366 RemoveEntryList (AdjacentLink
);
367 CoreFreePool (AdjacentEntry
);
374 Merge adjacent entries on total chain.
376 @param TopEntry Top entry of GCD map.
377 @param BottomEntry Bottom entry of GCD map.
378 @param StartLink Start link of the list for this loop.
379 @param EndLink End link of the list for this loop.
382 @retval EFI_SUCCESS GCD map successfully cleaned up.
386 CoreCleanupGcdMapEntry (
387 IN EFI_GCD_MAP_ENTRY
*TopEntry
,
388 IN EFI_GCD_MAP_ENTRY
*BottomEntry
,
389 IN LIST_ENTRY
*StartLink
,
390 IN LIST_ENTRY
*EndLink
,
396 if (TopEntry
->Signature
== 0) {
397 CoreFreePool (TopEntry
);
399 if (BottomEntry
->Signature
== 0) {
400 CoreFreePool (BottomEntry
);
404 while (Link
!= EndLink
->ForwardLink
) {
405 CoreMergeGcdMapEntry (Link
, FALSE
, Map
);
406 Link
= Link
->ForwardLink
;
408 CoreMergeGcdMapEntry (EndLink
, TRUE
, Map
);
415 Search a segment of memory space in GCD map. The result is a range of GCD entry list.
417 @param BaseAddress The start address of the segment.
418 @param Length The length of the segment.
419 @param StartLink The first GCD entry involves this segment of
421 @param EndLink The first GCD entry involves this segment of
423 @param Map Points to the start entry to search.
425 @retval EFI_SUCCESS Successfully found the entry.
426 @retval EFI_NOT_FOUND Not found.
430 CoreSearchGcdMapEntry (
431 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
433 OUT LIST_ENTRY
**StartLink
,
434 OUT LIST_ENTRY
**EndLink
,
439 EFI_GCD_MAP_ENTRY
*Entry
;
441 ASSERT (Length
!= 0);
446 Link
= Map
->ForwardLink
;
447 while (Link
!= Map
) {
448 Entry
= CR (Link
, EFI_GCD_MAP_ENTRY
, Link
, EFI_GCD_MAP_SIGNATURE
);
449 if (BaseAddress
>= Entry
->BaseAddress
&& BaseAddress
<= Entry
->EndAddress
) {
452 if (*StartLink
!= NULL
) {
453 if ((BaseAddress
+ Length
- 1) >= Entry
->BaseAddress
&&
454 (BaseAddress
+ Length
- 1) <= Entry
->EndAddress
) {
459 Link
= Link
->ForwardLink
;
462 return EFI_NOT_FOUND
;
467 Count the amount of GCD map entries.
469 @param Map Points to the start entry to do the count loop.
475 CoreCountGcdMapEntry (
483 Link
= Map
->ForwardLink
;
484 while (Link
!= Map
) {
486 Link
= Link
->ForwardLink
;
495 Return the memory attribute specified by Attributes
497 @param Attributes A num with some attribute bits on.
499 @return The enum value of memory attribute.
503 ConverToCpuArchAttributes (
507 if ( (Attributes
& EFI_MEMORY_UC
) == EFI_MEMORY_UC
) {
508 return EFI_MEMORY_UC
;
511 if ( (Attributes
& EFI_MEMORY_WC
) == EFI_MEMORY_WC
) {
512 return EFI_MEMORY_WC
;
515 if ( (Attributes
& EFI_MEMORY_WT
) == EFI_MEMORY_WT
) {
516 return EFI_MEMORY_WT
;
519 if ( (Attributes
& EFI_MEMORY_WB
) == EFI_MEMORY_WB
) {
520 return EFI_MEMORY_WB
;
523 if ( (Attributes
& EFI_MEMORY_WP
) == EFI_MEMORY_WP
) {
524 return EFI_MEMORY_WP
;
527 return INVALID_CPU_ARCH_ATTRIBUTES
;
533 Do operation on a segment of memory space specified (add, free, remove, change attribute ...).
535 @param Operation The type of the operation
536 @param GcdMemoryType Additional information for the operation
537 @param GcdIoType Additional information for the operation
538 @param BaseAddress Start address of the segment
539 @param Length length of the segment
540 @param Capabilities The alterable attributes of a newly added entry
541 @param Attributes The attributes needs to be set
543 @retval EFI_INVALID_PARAMETER Length is 0 or address (length) not aligned when
545 @retval EFI_SUCCESS Action successfully done.
546 @retval EFI_UNSUPPORTED Could not find the proper descriptor on this
547 segment or set an upsupported attribute.
548 @retval EFI_ACCESS_DENIED Operate on an space non-exist or is used for an
550 @retval EFI_NOT_FOUND Free a non-using space or remove a non-exist
552 @retval EFI_OUT_OF_RESOURCES No buffer could be allocated.
558 IN EFI_GCD_MEMORY_TYPE GcdMemoryType
,
559 IN EFI_GCD_IO_TYPE GcdIoType
,
560 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
562 IN UINT64 Capabilities
,
569 EFI_GCD_MAP_ENTRY
*Entry
;
570 EFI_GCD_MAP_ENTRY
*TopEntry
;
571 EFI_GCD_MAP_ENTRY
*BottomEntry
;
572 LIST_ENTRY
*StartLink
;
575 EFI_CPU_ARCH_PROTOCOL
*CpuArch
;
576 UINT64 CpuArchAttributes
;
579 return EFI_INVALID_PARAMETER
;
583 if ((Operation
& GCD_MEMORY_SPACE_OPERATION
) != 0) {
584 CoreAcquireGcdMemoryLock ();
585 Map
= &mGcdMemorySpaceMap
;
586 } else if ((Operation
& GCD_IO_SPACE_OPERATION
) != 0) {
587 CoreAcquireGcdIoLock ();
588 Map
= &mGcdIoSpaceMap
;
594 // Search for the list of descriptors that cover the range BaseAddress to BaseAddress+Length
596 Status
= CoreSearchGcdMapEntry (BaseAddress
, Length
, &StartLink
, &EndLink
, Map
);
597 if (EFI_ERROR (Status
)) {
598 Status
= EFI_UNSUPPORTED
;
604 // Verify that the list of descriptors are unallocated non-existent memory.
607 while (Link
!= EndLink
->ForwardLink
) {
608 Entry
= CR (Link
, EFI_GCD_MAP_ENTRY
, Link
, EFI_GCD_MAP_SIGNATURE
);
613 case GCD_ADD_MEMORY_OPERATION
:
614 if (Entry
->GcdMemoryType
!= EfiGcdMemoryTypeNonExistent
||
615 Entry
->ImageHandle
!= NULL
) {
616 Status
= EFI_ACCESS_DENIED
;
620 case GCD_ADD_IO_OPERATION
:
621 if (Entry
->GcdIoType
!= EfiGcdIoTypeNonExistent
||
622 Entry
->ImageHandle
!= NULL
) {
623 Status
= EFI_ACCESS_DENIED
;
630 case GCD_FREE_MEMORY_OPERATION
:
631 case GCD_FREE_IO_OPERATION
:
632 if (Entry
->ImageHandle
== NULL
) {
633 Status
= EFI_NOT_FOUND
;
640 case GCD_REMOVE_MEMORY_OPERATION
:
641 if (Entry
->GcdMemoryType
== EfiGcdMemoryTypeNonExistent
) {
642 Status
= EFI_NOT_FOUND
;
645 if (Entry
->ImageHandle
!= NULL
) {
646 Status
= EFI_ACCESS_DENIED
;
650 case GCD_REMOVE_IO_OPERATION
:
651 if (Entry
->GcdIoType
== EfiGcdIoTypeNonExistent
) {
652 Status
= EFI_NOT_FOUND
;
655 if (Entry
->ImageHandle
!= NULL
) {
656 Status
= EFI_ACCESS_DENIED
;
661 // Set attribute operations
663 case GCD_SET_ATTRIBUTES_MEMORY_OPERATION
:
664 if ((Attributes
& EFI_MEMORY_RUNTIME
) != 0) {
665 if ((BaseAddress
& EFI_PAGE_MASK
) != 0 || (Length
& EFI_PAGE_MASK
) != 0) {
666 Status
= EFI_INVALID_PARAMETER
;
670 if ((Entry
->Capabilities
& Attributes
) != Attributes
) {
671 Status
= EFI_UNSUPPORTED
;
676 Link
= Link
->ForwardLink
;
680 // Allocate work space to perform this operation
682 Status
= CoreAllocateGcdMapEntry (&TopEntry
, &BottomEntry
);
683 if (EFI_ERROR (Status
)) {
684 Status
= EFI_OUT_OF_RESOURCES
;
688 if (Operation
== GCD_SET_ATTRIBUTES_MEMORY_OPERATION
) {
690 // Call CPU Arch Protocol to attempt to set attributes on the range
692 CpuArchAttributes
= ConverToCpuArchAttributes (Attributes
);
693 if ( CpuArchAttributes
!= INVALID_CPU_ARCH_ATTRIBUTES
) {
694 Status
= CoreLocateProtocol (&gEfiCpuArchProtocolGuid
, NULL
, (VOID
**)&CpuArch
);
695 if (EFI_ERROR (Status
)) {
696 Status
= EFI_ACCESS_DENIED
;
700 Status
= CpuArch
->SetMemoryAttributes (
706 if (EFI_ERROR (Status
)) {
714 // Convert/Insert the list of descriptors from StartLink to EndLink
717 while (Link
!= EndLink
->ForwardLink
) {
718 Entry
= CR (Link
, EFI_GCD_MAP_ENTRY
, Link
, EFI_GCD_MAP_SIGNATURE
);
719 CoreInsertGcdMapEntry (Link
, Entry
, BaseAddress
, Length
, TopEntry
, BottomEntry
);
724 case GCD_ADD_MEMORY_OPERATION
:
725 Entry
->GcdMemoryType
= GcdMemoryType
;
726 if (GcdMemoryType
== EfiGcdMemoryTypeMemoryMappedIo
) {
727 Entry
->Capabilities
= Capabilities
| EFI_MEMORY_RUNTIME
| EFI_MEMORY_PORT_IO
;
729 Entry
->Capabilities
= Capabilities
| EFI_MEMORY_RUNTIME
;
732 case GCD_ADD_IO_OPERATION
:
733 Entry
->GcdIoType
= GcdIoType
;
738 case GCD_FREE_MEMORY_OPERATION
:
739 case GCD_FREE_IO_OPERATION
:
740 Entry
->ImageHandle
= NULL
;
741 Entry
->DeviceHandle
= NULL
;
746 case GCD_REMOVE_MEMORY_OPERATION
:
747 Entry
->GcdMemoryType
= EfiGcdMemoryTypeNonExistent
;
748 Entry
->Capabilities
= 0;
750 case GCD_REMOVE_IO_OPERATION
:
751 Entry
->GcdIoType
= EfiGcdIoTypeNonExistent
;
754 // Set attribute operations
756 case GCD_SET_ATTRIBUTES_MEMORY_OPERATION
:
757 Entry
->Attributes
= Attributes
;
760 Link
= Link
->ForwardLink
;
766 Status
= CoreCleanupGcdMapEntry (TopEntry
, BottomEntry
, StartLink
, EndLink
, Map
);
769 if ((Operation
& GCD_MEMORY_SPACE_OPERATION
) != 0) {
770 CoreReleaseGcdMemoryLock ();
772 if ((Operation
& GCD_IO_SPACE_OPERATION
) != 0) {
773 CoreReleaseGcdIoLock ();
781 Check whether an entry could be used to allocate space.
783 @param Operation Allocate memory or IO
784 @param Entry The entry to be tested
785 @param GcdMemoryType The desired memory type
786 @param GcdIoType The desired IO type
788 @retval EFI_NOT_FOUND The memory type does not match or there's an
789 image handle on the entry.
790 @retval EFI_UNSUPPORTED The operation unsupported.
791 @retval EFI_SUCCESS It's ok for this entry to be used to allocate
796 CoreAllocateSpaceCheckEntry (
798 IN EFI_GCD_MAP_ENTRY
*Entry
,
799 IN EFI_GCD_MEMORY_TYPE GcdMemoryType
,
800 IN EFI_GCD_IO_TYPE GcdIoType
803 if (Entry
->ImageHandle
!= NULL
) {
804 return EFI_NOT_FOUND
;
807 case GCD_ALLOCATE_MEMORY_OPERATION
:
808 if (Entry
->GcdMemoryType
!= GcdMemoryType
) {
809 return EFI_NOT_FOUND
;
812 case GCD_ALLOCATE_IO_OPERATION
:
813 if (Entry
->GcdIoType
!= GcdIoType
) {
814 return EFI_NOT_FOUND
;
818 return EFI_UNSUPPORTED
;
825 Allocate space on specified address and length.
827 @param Operation The type of operation (memory or IO)
828 @param GcdAllocateType The type of allocate operation
829 @param GcdMemoryType The desired memory type
830 @param GcdIoType The desired IO type
831 @param Alignment Align with 2^Alignment
832 @param Length Length to allocate
833 @param BaseAddress Base address to allocate
834 @param ImageHandle The image handle consume the allocated space.
835 @param DeviceHandle The device handle consume the allocated space.
837 @retval EFI_INVALID_PARAMETER Invalid parameter.
838 @retval EFI_NOT_FOUND No descriptor for the desired space exists.
839 @retval EFI_SUCCESS Space successfully allocated.
845 IN EFI_GCD_ALLOCATE_TYPE GcdAllocateType
,
846 IN EFI_GCD_MEMORY_TYPE GcdMemoryType
,
847 IN EFI_GCD_IO_TYPE GcdIoType
,
850 IN OUT EFI_PHYSICAL_ADDRESS
*BaseAddress
,
851 IN EFI_HANDLE ImageHandle
,
852 IN EFI_HANDLE DeviceHandle OPTIONAL
856 EFI_PHYSICAL_ADDRESS AlignmentMask
;
857 EFI_PHYSICAL_ADDRESS MaxAddress
;
861 EFI_GCD_MAP_ENTRY
*Entry
;
862 EFI_GCD_MAP_ENTRY
*TopEntry
;
863 EFI_GCD_MAP_ENTRY
*BottomEntry
;
864 LIST_ENTRY
*StartLink
;
869 // Make sure parameters are valid
871 if (GcdAllocateType
< 0 || GcdAllocateType
>= EfiGcdMaxAllocateType
) {
872 return EFI_INVALID_PARAMETER
;
874 if (GcdMemoryType
< 0 || GcdMemoryType
>= EfiGcdMemoryTypeMaximum
) {
875 return EFI_INVALID_PARAMETER
;
877 if (GcdIoType
< 0 || GcdIoType
>= EfiGcdIoTypeMaximum
) {
878 return EFI_INVALID_PARAMETER
;
880 if (BaseAddress
== NULL
) {
881 return EFI_INVALID_PARAMETER
;
883 if (ImageHandle
== NULL
) {
884 return EFI_INVALID_PARAMETER
;
886 if (Alignment
>= 64) {
887 return EFI_NOT_FOUND
;
890 return EFI_INVALID_PARAMETER
;
894 if ((Operation
& GCD_MEMORY_SPACE_OPERATION
) != 0) {
895 CoreAcquireGcdMemoryLock ();
896 Map
= &mGcdMemorySpaceMap
;
897 } else if ((Operation
& GCD_IO_SPACE_OPERATION
) != 0) {
898 CoreAcquireGcdIoLock ();
899 Map
= &mGcdIoSpaceMap
;
908 // Compute alignment bit mask
910 AlignmentMask
= LShiftU64 (1, Alignment
) - 1;
912 if (GcdAllocateType
== EfiGcdAllocateAddress
) {
914 // Verify that the BaseAddress passed in is aligned correctly
916 if ((*BaseAddress
& AlignmentMask
) != 0) {
917 Status
= EFI_NOT_FOUND
;
922 // Search for the list of descriptors that cover the range BaseAddress to BaseAddress+Length
924 Status
= CoreSearchGcdMapEntry (*BaseAddress
, Length
, &StartLink
, &EndLink
, Map
);
925 if (EFI_ERROR (Status
)) {
926 Status
= EFI_NOT_FOUND
;
931 // Verify that the list of descriptors are unallocated memory matching GcdMemoryType.
934 while (Link
!= EndLink
->ForwardLink
) {
935 Entry
= CR (Link
, EFI_GCD_MAP_ENTRY
, Link
, EFI_GCD_MAP_SIGNATURE
);
936 Link
= Link
->ForwardLink
;
937 Status
= CoreAllocateSpaceCheckEntry (Operation
, Entry
, GcdMemoryType
, GcdIoType
);
938 if (EFI_ERROR (Status
)) {
945 Entry
= CR (Map
->BackLink
, EFI_GCD_MAP_ENTRY
, Link
, EFI_GCD_MAP_SIGNATURE
);
948 // Compute the maximum address to use in the search algorithm
950 if (GcdAllocateType
== EfiGcdAllocateMaxAddressSearchBottomUp
||
951 GcdAllocateType
== EfiGcdAllocateMaxAddressSearchTopDown
) {
952 MaxAddress
= *BaseAddress
;
954 MaxAddress
= Entry
->EndAddress
;
958 // Verify that the list of descriptors are unallocated memory matching GcdMemoryType.
960 if (GcdAllocateType
== EfiGcdAllocateMaxAddressSearchTopDown
||
961 GcdAllocateType
== EfiGcdAllocateAnySearchTopDown
) {
962 Link
= Map
->BackLink
;
964 Link
= Map
->ForwardLink
;
966 while (Link
!= Map
) {
967 Entry
= CR (Link
, EFI_GCD_MAP_ENTRY
, Link
, EFI_GCD_MAP_SIGNATURE
);
969 if (GcdAllocateType
== EfiGcdAllocateMaxAddressSearchTopDown
||
970 GcdAllocateType
== EfiGcdAllocateAnySearchTopDown
) {
971 Link
= Link
->BackLink
;
973 Link
= Link
->ForwardLink
;
976 Status
= CoreAllocateSpaceCheckEntry (Operation
, Entry
, GcdMemoryType
, GcdIoType
);
977 if (EFI_ERROR (Status
)) {
981 if (GcdAllocateType
== EfiGcdAllocateMaxAddressSearchTopDown
||
982 GcdAllocateType
== EfiGcdAllocateAnySearchTopDown
) {
983 if ((Entry
->BaseAddress
+ Length
) > MaxAddress
) {
986 if (Length
> (Entry
->EndAddress
+ 1)) {
987 Status
= EFI_NOT_FOUND
;
990 if (Entry
->EndAddress
> MaxAddress
) {
991 *BaseAddress
= MaxAddress
;
993 *BaseAddress
= Entry
->EndAddress
;
995 *BaseAddress
= (*BaseAddress
+ 1 - Length
) & (~AlignmentMask
);
997 *BaseAddress
= (Entry
->BaseAddress
+ AlignmentMask
) & (~AlignmentMask
);
998 if ((*BaseAddress
+ Length
- 1) > MaxAddress
) {
999 Status
= EFI_NOT_FOUND
;
1005 // Search for the list of descriptors that cover the range BaseAddress to BaseAddress+Length
1007 Status
= CoreSearchGcdMapEntry (*BaseAddress
, Length
, &StartLink
, &EndLink
, Map
);
1008 if (EFI_ERROR (Status
)) {
1009 Status
= EFI_NOT_FOUND
;
1015 // Verify that the list of descriptors are unallocated memory matching GcdMemoryType.
1018 SubLink
= StartLink
;
1019 while (SubLink
!= EndLink
->ForwardLink
) {
1020 Entry
= CR (SubLink
, EFI_GCD_MAP_ENTRY
, Link
, EFI_GCD_MAP_SIGNATURE
);
1021 Status
= CoreAllocateSpaceCheckEntry (Operation
, Entry
, GcdMemoryType
, GcdIoType
);
1022 if (EFI_ERROR (Status
)) {
1027 SubLink
= SubLink
->ForwardLink
;
1035 Status
= EFI_NOT_FOUND
;
1040 // Allocate work space to perform this operation
1042 Status
= CoreAllocateGcdMapEntry (&TopEntry
, &BottomEntry
);
1043 if (EFI_ERROR (Status
)) {
1044 Status
= EFI_OUT_OF_RESOURCES
;
1049 // Convert/Insert the list of descriptors from StartLink to EndLink
1052 while (Link
!= EndLink
->ForwardLink
) {
1053 Entry
= CR (Link
, EFI_GCD_MAP_ENTRY
, Link
, EFI_GCD_MAP_SIGNATURE
);
1054 CoreInsertGcdMapEntry (Link
, Entry
, *BaseAddress
, Length
, TopEntry
, BottomEntry
);
1055 Entry
->ImageHandle
= ImageHandle
;
1056 Entry
->DeviceHandle
= DeviceHandle
;
1057 Link
= Link
->ForwardLink
;
1063 Status
= CoreCleanupGcdMapEntry (TopEntry
, BottomEntry
, StartLink
, EndLink
, Map
);
1066 if ((Operation
& GCD_MEMORY_SPACE_OPERATION
) != 0) {
1067 CoreReleaseGcdMemoryLock ();
1069 if ((Operation
& GCD_IO_SPACE_OPERATION
) !=0) {
1070 CoreReleaseGcdIoLock ();
1078 Add a segment of memory to GCD map.
1080 @param GcdMemoryType Memory type of the segment.
1081 @param BaseAddress Base address of the segment.
1082 @param Length Length of the segment.
1083 @param Capabilities alterable attributes of the segment.
1085 @retval EFI_INVALID_PARAMETER Invalid parameters.
1086 @retval EFI_SUCCESS Successfully add a segment of memory space.
1090 CoreInternalAddMemorySpace (
1091 IN EFI_GCD_MEMORY_TYPE GcdMemoryType
,
1092 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
1094 IN UINT64 Capabilities
1098 // Make sure parameters are valid
1100 if (GcdMemoryType
<= EfiGcdMemoryTypeNonExistent
|| GcdMemoryType
>= EfiGcdMemoryTypeMaximum
) {
1101 return EFI_INVALID_PARAMETER
;
1104 return CoreConvertSpace (GCD_ADD_MEMORY_OPERATION
, GcdMemoryType
, (EFI_GCD_IO_TYPE
) 0, BaseAddress
, Length
, Capabilities
, 0);
1108 // GCD Core Services
1112 Allocates nonexistent memory, reserved memory, system memory, or memorymapped
1113 I/O resources from the global coherency domain of the processor.
1115 @param GcdAllocateType The type of allocate operation
1116 @param GcdMemoryType The desired memory type
1117 @param Alignment Align with 2^Alignment
1118 @param Length Length to allocate
1119 @param BaseAddress Base address to allocate
1120 @param ImageHandle The image handle consume the allocated space.
1121 @param DeviceHandle The device handle consume the allocated space.
1123 @retval EFI_INVALID_PARAMETER Invalid parameter.
1124 @retval EFI_NOT_FOUND No descriptor contains the desired space.
1125 @retval EFI_SUCCESS Memory space successfully allocated.
1130 CoreAllocateMemorySpace (
1131 IN EFI_GCD_ALLOCATE_TYPE GcdAllocateType
,
1132 IN EFI_GCD_MEMORY_TYPE GcdMemoryType
,
1135 IN OUT EFI_PHYSICAL_ADDRESS
*BaseAddress
,
1136 IN EFI_HANDLE ImageHandle
,
1137 IN EFI_HANDLE DeviceHandle OPTIONAL
1140 return CoreAllocateSpace (
1141 GCD_ALLOCATE_MEMORY_OPERATION
,
1144 (EFI_GCD_IO_TYPE
) 0,
1155 Adds reserved memory, system memory, or memory-mapped I/O resources to the
1156 global coherency domain of the processor.
1158 @param GcdMemoryType Memory type of the memory space.
1159 @param BaseAddress Base address of the memory space.
1160 @param Length Length of the memory space.
1161 @param Capabilities alterable attributes of the memory space.
1163 @retval EFI_SUCCESS Merged this memory space into GCD map.
1168 CoreAddMemorySpace (
1169 IN EFI_GCD_MEMORY_TYPE GcdMemoryType
,
1170 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
1172 IN UINT64 Capabilities
1176 EFI_PHYSICAL_ADDRESS PageBaseAddress
;
1179 Status
= CoreInternalAddMemorySpace (GcdMemoryType
, BaseAddress
, Length
, Capabilities
);
1181 if (!EFI_ERROR (Status
) && GcdMemoryType
== EfiGcdMemoryTypeSystemMemory
) {
1183 PageBaseAddress
= PageAlignLength (BaseAddress
);
1184 PageLength
= PageAlignLength (BaseAddress
+ Length
- PageBaseAddress
);
1186 Status
= CoreAllocateMemorySpace (
1187 EfiGcdAllocateAddress
,
1192 gDxeCoreImageHandle
,
1196 if (!EFI_ERROR (Status
)) {
1197 CoreAddMemoryDescriptor (
1198 EfiConventionalMemory
,
1200 RShiftU64 (PageLength
, EFI_PAGE_SHIFT
),
1204 for (; PageLength
!= 0; PageLength
-= EFI_PAGE_SIZE
, PageBaseAddress
+= EFI_PAGE_SIZE
) {
1205 Status
= CoreAllocateMemorySpace (
1206 EfiGcdAllocateAddress
,
1211 gDxeCoreImageHandle
,
1215 if (!EFI_ERROR (Status
)) {
1216 CoreAddMemoryDescriptor (
1217 EfiConventionalMemory
,
1231 Frees nonexistent memory, reserved memory, system memory, or memory-mapped
1232 I/O resources from the global coherency domain of the processor.
1234 @param BaseAddress Base address of the memory space.
1235 @param Length Length of the memory space.
1237 @retval EFI_SUCCESS Space successfully freed.
1242 CoreFreeMemorySpace (
1243 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
1247 return CoreConvertSpace (GCD_FREE_MEMORY_OPERATION
, (EFI_GCD_MEMORY_TYPE
) 0, (EFI_GCD_IO_TYPE
) 0, BaseAddress
, Length
, 0, 0);
1252 Removes reserved memory, system memory, or memory-mapped I/O resources from
1253 the global coherency domain of the processor.
1255 @param BaseAddress Base address of the memory space.
1256 @param Length Length of the memory space.
1258 @retval EFI_SUCCESS Successfully remove a segment of memory space.
1263 CoreRemoveMemorySpace (
1264 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
1268 return CoreConvertSpace (GCD_REMOVE_MEMORY_OPERATION
, (EFI_GCD_MEMORY_TYPE
) 0, (EFI_GCD_IO_TYPE
) 0, BaseAddress
, Length
, 0, 0);
1273 Build a memory descriptor according to an entry.
1275 @param Descriptor The descriptor to be built
1276 @param Entry According to this entry
1280 BuildMemoryDescriptor (
1281 IN OUT EFI_GCD_MEMORY_SPACE_DESCRIPTOR
*Descriptor
,
1282 IN EFI_GCD_MAP_ENTRY
*Entry
1285 Descriptor
->BaseAddress
= Entry
->BaseAddress
;
1286 Descriptor
->Length
= Entry
->EndAddress
- Entry
->BaseAddress
+ 1;
1287 Descriptor
->Capabilities
= Entry
->Capabilities
;
1288 Descriptor
->Attributes
= Entry
->Attributes
;
1289 Descriptor
->GcdMemoryType
= Entry
->GcdMemoryType
;
1290 Descriptor
->ImageHandle
= Entry
->ImageHandle
;
1291 Descriptor
->DeviceHandle
= Entry
->DeviceHandle
;
1296 Retrieves the descriptor for a memory region containing a specified address.
1298 @param BaseAddress Specified start address
1299 @param Descriptor Specified length
1301 @retval EFI_INVALID_PARAMETER Invalid parameter
1302 @retval EFI_SUCCESS Successfully get memory space descriptor.
1307 CoreGetMemorySpaceDescriptor (
1308 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
1309 OUT EFI_GCD_MEMORY_SPACE_DESCRIPTOR
*Descriptor
1313 LIST_ENTRY
*StartLink
;
1314 LIST_ENTRY
*EndLink
;
1315 EFI_GCD_MAP_ENTRY
*Entry
;
1318 // Make sure parameters are valid
1320 if (Descriptor
== NULL
) {
1321 return EFI_INVALID_PARAMETER
;
1324 CoreAcquireGcdMemoryLock ();
1327 // Search for the list of descriptors that contain BaseAddress
1329 Status
= CoreSearchGcdMapEntry (BaseAddress
, 1, &StartLink
, &EndLink
, &mGcdMemorySpaceMap
);
1330 if (EFI_ERROR (Status
)) {
1331 Status
= EFI_NOT_FOUND
;
1334 // Copy the contents of the found descriptor into Descriptor
1336 Entry
= CR (StartLink
, EFI_GCD_MAP_ENTRY
, Link
, EFI_GCD_MAP_SIGNATURE
);
1337 BuildMemoryDescriptor (Descriptor
, Entry
);
1340 CoreReleaseGcdMemoryLock ();
1347 Modifies the attributes for a memory region in the global coherency domain of the
1350 @param BaseAddress Specified start address
1351 @param Length Specified length
1352 @param Attributes Specified attributes
1354 @retval EFI_SUCCESS Successfully set attribute of a segment of
1360 CoreSetMemorySpaceAttributes (
1361 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
1363 IN UINT64 Attributes
1366 return CoreConvertSpace (GCD_SET_ATTRIBUTES_MEMORY_OPERATION
, (EFI_GCD_MEMORY_TYPE
) 0, (EFI_GCD_IO_TYPE
) 0, BaseAddress
, Length
, 0, Attributes
);
1371 Returns a map of the memory resources in the global coherency domain of the
1374 @param NumberOfDescriptors Number of descriptors.
1375 @param MemorySpaceMap Descriptor array
1377 @retval EFI_INVALID_PARAMETER Invalid parameter
1378 @retval EFI_OUT_OF_RESOURCES No enough buffer to allocate
1379 @retval EFI_SUCCESS Successfully get memory space map.
1384 CoreGetMemorySpaceMap (
1385 OUT UINTN
*NumberOfDescriptors
,
1386 OUT EFI_GCD_MEMORY_SPACE_DESCRIPTOR
**MemorySpaceMap
1391 EFI_GCD_MAP_ENTRY
*Entry
;
1392 EFI_GCD_MEMORY_SPACE_DESCRIPTOR
*Descriptor
;
1395 // Make sure parameters are valid
1397 if (NumberOfDescriptors
== NULL
) {
1398 return EFI_INVALID_PARAMETER
;
1400 if (MemorySpaceMap
== NULL
) {
1401 return EFI_INVALID_PARAMETER
;
1404 CoreAcquireGcdMemoryLock ();
1407 // Count the number of descriptors
1409 *NumberOfDescriptors
= CoreCountGcdMapEntry (&mGcdMemorySpaceMap
);
1412 // Allocate the MemorySpaceMap
1414 *MemorySpaceMap
= AllocatePool (*NumberOfDescriptors
* sizeof (EFI_GCD_MEMORY_SPACE_DESCRIPTOR
));
1415 if (*MemorySpaceMap
== NULL
) {
1416 Status
= EFI_OUT_OF_RESOURCES
;
1421 // Fill in the MemorySpaceMap
1423 Descriptor
= *MemorySpaceMap
;
1424 Link
= mGcdMemorySpaceMap
.ForwardLink
;
1425 while (Link
!= &mGcdMemorySpaceMap
) {
1426 Entry
= CR (Link
, EFI_GCD_MAP_ENTRY
, Link
, EFI_GCD_MAP_SIGNATURE
);
1427 BuildMemoryDescriptor (Descriptor
, Entry
);
1429 Link
= Link
->ForwardLink
;
1431 Status
= EFI_SUCCESS
;
1434 CoreReleaseGcdMemoryLock ();
1440 Adds reserved I/O or I/O resources to the global coherency domain of the processor.
1442 @param GcdIoType IO type of the segment.
1443 @param BaseAddress Base address of the segment.
1444 @param Length Length of the segment.
1446 @retval EFI_SUCCESS Merged this segment into GCD map.
1447 @retval EFI_INVALID_PARAMETER Parameter not valid
1453 IN EFI_GCD_IO_TYPE GcdIoType
,
1454 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
1459 // Make sure parameters are valid
1461 if (GcdIoType
<= EfiGcdIoTypeNonExistent
|| GcdIoType
>= EfiGcdIoTypeMaximum
) {
1462 return EFI_INVALID_PARAMETER
;
1464 return CoreConvertSpace (GCD_ADD_IO_OPERATION
, (EFI_GCD_MEMORY_TYPE
) 0, GcdIoType
, BaseAddress
, Length
, 0, 0);
1469 Allocates nonexistent I/O, reserved I/O, or I/O resources from the global coherency
1470 domain of the processor.
1472 @param GcdAllocateType The type of allocate operation
1473 @param GcdIoType The desired IO type
1474 @param Alignment Align with 2^Alignment
1475 @param Length Length to allocate
1476 @param BaseAddress Base address to allocate
1477 @param ImageHandle The image handle consume the allocated space.
1478 @param DeviceHandle The device handle consume the allocated space.
1480 @retval EFI_INVALID_PARAMETER Invalid parameter.
1481 @retval EFI_NOT_FOUND No descriptor contains the desired space.
1482 @retval EFI_SUCCESS IO space successfully allocated.
1487 CoreAllocateIoSpace (
1488 IN EFI_GCD_ALLOCATE_TYPE GcdAllocateType
,
1489 IN EFI_GCD_IO_TYPE GcdIoType
,
1492 IN OUT EFI_PHYSICAL_ADDRESS
*BaseAddress
,
1493 IN EFI_HANDLE ImageHandle
,
1494 IN EFI_HANDLE DeviceHandle OPTIONAL
1497 return CoreAllocateSpace (
1498 GCD_ALLOCATE_IO_OPERATION
,
1500 (EFI_GCD_MEMORY_TYPE
) 0,
1512 Frees nonexistent I/O, reserved I/O, or I/O resources from the global coherency
1513 domain of the processor.
1515 @param BaseAddress Base address of the segment.
1516 @param Length Length of the segment.
1518 @retval EFI_SUCCESS Space successfully freed.
1524 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
1528 return CoreConvertSpace (GCD_FREE_IO_OPERATION
, (EFI_GCD_MEMORY_TYPE
) 0, (EFI_GCD_IO_TYPE
) 0, BaseAddress
, Length
, 0, 0);
1533 Removes reserved I/O or I/O resources from the global coherency domain of the
1536 @param BaseAddress Base address of the segment.
1537 @param Length Length of the segment.
1539 @retval EFI_SUCCESS Successfully removed a segment of IO space.
1545 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
1549 return CoreConvertSpace (GCD_REMOVE_IO_OPERATION
, (EFI_GCD_MEMORY_TYPE
) 0, (EFI_GCD_IO_TYPE
) 0, BaseAddress
, Length
, 0, 0);
1554 Build a IO descriptor according to an entry.
1556 @param Descriptor The descriptor to be built
1557 @param Entry According to this entry
1562 IN EFI_GCD_IO_SPACE_DESCRIPTOR
*Descriptor
,
1563 IN EFI_GCD_MAP_ENTRY
*Entry
1566 Descriptor
->BaseAddress
= Entry
->BaseAddress
;
1567 Descriptor
->Length
= Entry
->EndAddress
- Entry
->BaseAddress
+ 1;
1568 Descriptor
->GcdIoType
= Entry
->GcdIoType
;
1569 Descriptor
->ImageHandle
= Entry
->ImageHandle
;
1570 Descriptor
->DeviceHandle
= Entry
->DeviceHandle
;
1575 Retrieves the descriptor for an I/O region containing a specified address.
1577 @param BaseAddress Specified start address
1578 @param Descriptor Specified length
1580 @retval EFI_INVALID_PARAMETER Descriptor is NULL.
1581 @retval EFI_SUCCESS Successfully get the IO space descriptor.
1586 CoreGetIoSpaceDescriptor (
1587 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
1588 OUT EFI_GCD_IO_SPACE_DESCRIPTOR
*Descriptor
1592 LIST_ENTRY
*StartLink
;
1593 LIST_ENTRY
*EndLink
;
1594 EFI_GCD_MAP_ENTRY
*Entry
;
1597 // Make sure parameters are valid
1599 if (Descriptor
== NULL
) {
1600 return EFI_INVALID_PARAMETER
;
1603 CoreAcquireGcdIoLock ();
1606 // Search for the list of descriptors that contain BaseAddress
1608 Status
= CoreSearchGcdMapEntry (BaseAddress
, 1, &StartLink
, &EndLink
, &mGcdIoSpaceMap
);
1609 if (EFI_ERROR (Status
)) {
1610 Status
= EFI_NOT_FOUND
;
1613 // Copy the contents of the found descriptor into Descriptor
1615 Entry
= CR (StartLink
, EFI_GCD_MAP_ENTRY
, Link
, EFI_GCD_MAP_SIGNATURE
);
1616 BuildIoDescriptor (Descriptor
, Entry
);
1619 CoreReleaseGcdIoLock ();
1626 Returns a map of the I/O resources in the global coherency domain of the processor.
1628 @param NumberOfDescriptors Number of descriptors.
1629 @param IoSpaceMap Descriptor array
1631 @retval EFI_INVALID_PARAMETER Invalid parameter
1632 @retval EFI_OUT_OF_RESOURCES No enough buffer to allocate
1633 @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
= AllocatePool (*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.
1705 CoreConvertResourceDescriptorHobAttributesToCapabilities (
1706 EFI_GCD_MEMORY_TYPE GcdMemoryType
,
1710 UINT64 Capabilities
;
1711 GCD_ATTRIBUTE_CONVERSION_ENTRY
*Conversion
;
1714 // Convert the Resource HOB Attributes to an EFI Memory Capabilities mask
1716 for (Capabilities
= 0, Conversion
= mAttributeConversionTable
; Conversion
->Attribute
!= 0; Conversion
++) {
1717 if (Conversion
->Memory
|| (GcdMemoryType
!= EfiGcdMemoryTypeSystemMemory
)) {
1718 if (Attributes
& Conversion
->Attribute
) {
1719 Capabilities
|= Conversion
->Capability
;
1724 return Capabilities
;
1729 External function. Initializes memory services based on the memory
1730 descriptor HOBs. This function is responsible for priming the memory
1731 map, so memory allocations and resource allocations can be made.
1732 The first part of this function can not depend on any memory services
1733 until at least one memory descriptor is provided to the memory services.
1735 @param HobStart The start address of the HOB.
1736 @param MemoryBaseAddress Start address of memory region found to init DXE
1738 @param MemoryLength Length of memory region found to init DXE core.
1740 @retval EFI_SUCCESS Memory services successfully initialized.
1744 CoreInitializeMemoryServices (
1746 OUT EFI_PHYSICAL_ADDRESS
*MemoryBaseAddress
,
1747 OUT UINT64
*MemoryLength
1750 EFI_PEI_HOB_POINTERS Hob
;
1751 EFI_MEMORY_TYPE_INFORMATION
*EfiMemoryTypeInformation
;
1754 EFI_HOB_HANDOFF_INFO_TABLE
*PhitHob
;
1755 EFI_HOB_RESOURCE_DESCRIPTOR
*ResourceHob
;
1756 EFI_HOB_RESOURCE_DESCRIPTOR
*PhitResourceHob
;
1757 EFI_PHYSICAL_ADDRESS BaseAddress
;
1760 UINT64 Capabilities
;
1761 EFI_PHYSICAL_ADDRESS MaxMemoryBaseAddress
;
1762 UINT64 MaxMemoryLength
;
1763 UINT64 MaxMemoryAttributes
;
1764 EFI_PHYSICAL_ADDRESS MaxAddress
;
1765 EFI_PHYSICAL_ADDRESS HighAddress
;
1766 EFI_HOB_RESOURCE_DESCRIPTOR
*MaxResourceHob
;
1767 EFI_HOB_GUID_TYPE
*GuidHob
;
1770 // Point at the first HOB. This must be the PHIT HOB.
1772 Hob
.Raw
= *HobStart
;
1773 ASSERT (GET_HOB_TYPE (Hob
) == EFI_HOB_TYPE_HANDOFF
);
1776 // Initialize the spin locks and maps in the memory services.
1777 // Also fill in the memory services into the EFI Boot Services Table
1779 CoreInitializePool ();
1782 // Initialize Local Variables
1784 PhitResourceHob
= NULL
;
1785 MaxResourceHob
= NULL
;
1790 MaxMemoryBaseAddress
= 0;
1791 MaxMemoryLength
= 0;
1792 MaxMemoryAttributes
= 0;
1795 // Cache the PHIT HOB for later use
1797 PhitHob
= Hob
.HandoffInformationTable
;
1800 // See if a Memory Type Information HOB is available
1802 GuidHob
= GetFirstGuidHob (&gEfiMemoryTypeInformationGuid
);
1803 if (GuidHob
!= NULL
) {
1804 EfiMemoryTypeInformation
= GET_GUID_HOB_DATA (GuidHob
);
1805 DataSize
= GET_GUID_HOB_DATA_SIZE (GuidHob
);
1806 if (EfiMemoryTypeInformation
!= NULL
&& DataSize
> 0 && DataSize
<= (EfiMaxMemoryType
+ 1) * sizeof (EFI_MEMORY_TYPE_INFORMATION
)) {
1807 CopyMem (&gMemoryTypeInformation
, EfiMemoryTypeInformation
, DataSize
);
1812 // Find the Resource Descriptor HOB that contains range FreeMemoryBaseAddress..FreeMemoryLength
1816 for (Hob
.Raw
= *HobStart
; !END_OF_HOB_LIST(Hob
); Hob
.Raw
= GET_NEXT_HOB(Hob
)) {
1818 if (GET_HOB_TYPE (Hob
) == EFI_HOB_TYPE_RESOURCE_DESCRIPTOR
) {
1820 ResourceHob
= Hob
.ResourceDescriptor
;
1822 if (ResourceHob
->ResourceType
== EFI_RESOURCE_SYSTEM_MEMORY
&&
1823 (ResourceHob
->ResourceAttribute
& MEMORY_ATTRIBUTE_MASK
) == TESTED_MEMORY_ATTRIBUTES
) {
1825 if (PhitHob
->EfiFreeMemoryBottom
>= ResourceHob
->PhysicalStart
&&
1826 PhitHob
->EfiFreeMemoryTop
<= (ResourceHob
->PhysicalStart
+ ResourceHob
->ResourceLength
) ) {
1829 // Cache the resource descriptor HOB for the memory region described by the PHIT HOB
1831 PhitResourceHob
= ResourceHob
;
1834 Attributes
= PhitResourceHob
->ResourceAttribute
;
1835 BaseAddress
= PageAlignAddress (PhitHob
->EfiMemoryTop
);
1836 Length
= PageAlignLength (ResourceHob
->PhysicalStart
+ ResourceHob
->ResourceLength
- BaseAddress
);
1837 if (Length
< MINIMUM_INITIAL_MEMORY_SIZE
) {
1838 BaseAddress
= PageAlignAddress (PhitHob
->EfiFreeMemoryBottom
);
1839 Length
= PageAlignLength (PhitHob
->EfiFreeMemoryTop
- BaseAddress
);
1840 if (Length
< MINIMUM_INITIAL_MEMORY_SIZE
) {
1841 BaseAddress
= PageAlignAddress (ResourceHob
->PhysicalStart
);
1842 Length
= PageAlignLength ((UINT64
)((UINTN
)*HobStart
- BaseAddress
));
1852 // Assert if a resource descriptor HOB for the memory region described by the PHIT was not found
1857 // Search all the resource descriptor HOBs from the highest possible addresses down for a memory
1858 // region that is big enough to initialize the DXE core. Always skip the PHIT Resource HOB.
1859 // The max address must be within the physically addressible range for the processor.
1861 MaxMemoryLength
= 0;
1862 MaxAddress
= MAX_ADDRESS
;
1867 // Search for a tested memory region that is below MaxAddress
1869 for (Hob
.Raw
= *HobStart
; !END_OF_HOB_LIST(Hob
); Hob
.Raw
= GET_NEXT_HOB(Hob
)) {
1872 // See if this is a resource descriptor HOB that does not contain the PHIT.
1874 if (Hob
.ResourceDescriptor
!= PhitResourceHob
&& GET_HOB_TYPE (Hob
) == EFI_HOB_TYPE_RESOURCE_DESCRIPTOR
) {
1876 ResourceHob
= Hob
.ResourceDescriptor
;
1878 // See if this resource descrior HOB describes tested system memory below MaxAddress
1880 if (ResourceHob
->ResourceType
== EFI_RESOURCE_SYSTEM_MEMORY
&&
1881 (ResourceHob
->ResourceAttribute
& MEMORY_ATTRIBUTE_MASK
) == TESTED_MEMORY_ATTRIBUTES
&&
1882 ResourceHob
->PhysicalStart
+ ResourceHob
->ResourceLength
<= MaxAddress
) {
1884 // See if this is the highest tested system memory region below MaxAddress
1886 if (ResourceHob
->PhysicalStart
> HighAddress
) {
1888 MaxResourceHob
= ResourceHob
;
1889 HighAddress
= MaxResourceHob
->PhysicalStart
;
1897 // Compute the size of the tested memory region below MaxAddrees
1899 MaxMemoryBaseAddress
= PageAlignAddress (MaxResourceHob
->PhysicalStart
);
1900 MaxMemoryLength
= PageAlignLength (MaxResourceHob
->PhysicalStart
+ MaxResourceHob
->ResourceLength
- MaxMemoryBaseAddress
);
1901 MaxMemoryAttributes
= MaxResourceHob
->ResourceAttribute
;
1903 MaxAddress
= ResourceHob
->PhysicalStart
;
1904 } while (Found
&& MaxMemoryLength
< MINIMUM_INITIAL_MEMORY_SIZE
);
1906 if ((Length
< MINIMUM_INITIAL_MEMORY_SIZE
) ||
1907 (MaxMemoryBaseAddress
> BaseAddress
&& MaxMemoryLength
>= MINIMUM_INITIAL_MEMORY_SIZE
)) {
1908 BaseAddress
= MaxMemoryBaseAddress
;
1909 Length
= MaxMemoryLength
;
1910 Attributes
= MaxMemoryAttributes
;
1914 // If no memory regions are found that are big enough to initialize the DXE core, then ASSERT().
1916 ASSERT (Length
>= MINIMUM_INITIAL_MEMORY_SIZE
);
1919 // Convert the Resource HOB Attributes to an EFI Memory Capabilities mask
1921 Capabilities
= CoreConvertResourceDescriptorHobAttributesToCapabilities (EfiGcdMemoryTypeSystemMemory
, Attributes
);
1924 // Declare the very first memory region, so the EFI Memory Services are available.
1926 CoreAddMemoryDescriptor (
1927 EfiConventionalMemory
,
1929 RShiftU64 (Length
, EFI_PAGE_SHIFT
),
1933 *MemoryBaseAddress
= BaseAddress
;
1934 *MemoryLength
= Length
;
1941 External function. Initializes the GCD and memory services based on the memory
1942 descriptor HOBs. This function is responsible for priming the GCD map and the
1943 memory map, so memory allocations and resource allocations can be made. The
1944 HobStart will be relocated to a pool buffer.
1946 @param HobStart The start address of the HOB
1947 @param MemoryBaseAddress Start address of memory region found to init DXE
1949 @param MemoryLength Length of memory region found to init DXE core.
1951 @retval EFI_SUCCESS GCD services successfully initialized.
1955 CoreInitializeGcdServices (
1956 IN OUT VOID
**HobStart
,
1957 IN EFI_PHYSICAL_ADDRESS MemoryBaseAddress
,
1958 IN UINT64 MemoryLength
1961 EFI_PEI_HOB_POINTERS Hob
;
1963 EFI_HOB_HANDOFF_INFO_TABLE
*PhitHob
;
1964 UINT8 SizeOfMemorySpace
;
1965 UINT8 SizeOfIoSpace
;
1966 EFI_HOB_RESOURCE_DESCRIPTOR
*ResourceHob
;
1967 EFI_PHYSICAL_ADDRESS BaseAddress
;
1970 EFI_GCD_MAP_ENTRY
*Entry
;
1971 EFI_GCD_MEMORY_TYPE GcdMemoryType
;
1972 EFI_GCD_IO_TYPE GcdIoType
;
1973 EFI_GCD_MEMORY_SPACE_DESCRIPTOR Descriptor
;
1974 EFI_HOB_MEMORY_ALLOCATION
*MemoryHob
;
1975 EFI_HOB_FIRMWARE_VOLUME
*FirmwareVolumeHob
;
1976 UINTN NumberOfDescriptors
;
1977 EFI_GCD_MEMORY_SPACE_DESCRIPTOR
*MemorySpaceMap
;
1979 UINT64 Capabilities
;
1980 EFI_HOB_CPU
* CpuHob
;
1983 // Cache the PHIT HOB for later use
1985 PhitHob
= (EFI_HOB_HANDOFF_INFO_TABLE
*)(*HobStart
);
1988 // Get the number of address lines in the I/O and Memory space for the CPU
1990 CpuHob
= GetFirstHob (EFI_HOB_TYPE_CPU
);
1991 ASSERT (CpuHob
!= NULL
);
1992 SizeOfMemorySpace
= CpuHob
->SizeOfMemorySpace
;
1993 SizeOfIoSpace
= CpuHob
->SizeOfIoSpace
;
1996 // Initialize the GCD Memory Space Map
1998 Entry
= AllocateCopyPool (sizeof (EFI_GCD_MAP_ENTRY
), &mGcdMemorySpaceMapEntryTemplate
);
1999 ASSERT (Entry
!= NULL
);
2001 Entry
->EndAddress
= LShiftU64 (1, SizeOfMemorySpace
) - 1;
2003 InsertHeadList (&mGcdMemorySpaceMap
, &Entry
->Link
);
2006 // Initialize the GCD I/O Space Map
2008 Entry
= AllocateCopyPool (sizeof (EFI_GCD_MAP_ENTRY
), &mGcdIoSpaceMapEntryTemplate
);
2009 ASSERT (Entry
!= NULL
);
2011 Entry
->EndAddress
= LShiftU64 (1, SizeOfIoSpace
) - 1;
2013 InsertHeadList (&mGcdIoSpaceMap
, &Entry
->Link
);
2016 // Walk the HOB list and add all resource descriptors to the GCD
2018 for (Hob
.Raw
= *HobStart
; !END_OF_HOB_LIST(Hob
); Hob
.Raw
= GET_NEXT_HOB(Hob
)) {
2020 GcdMemoryType
= EfiGcdMemoryTypeNonExistent
;
2021 GcdIoType
= EfiGcdIoTypeNonExistent
;
2023 if (GET_HOB_TYPE (Hob
) == EFI_HOB_TYPE_RESOURCE_DESCRIPTOR
) {
2025 ResourceHob
= Hob
.ResourceDescriptor
;
2027 switch (ResourceHob
->ResourceType
) {
2028 case EFI_RESOURCE_SYSTEM_MEMORY
:
2029 if ((ResourceHob
->ResourceAttribute
& MEMORY_ATTRIBUTE_MASK
) == TESTED_MEMORY_ATTRIBUTES
) {
2030 GcdMemoryType
= EfiGcdMemoryTypeSystemMemory
;
2032 if ((ResourceHob
->ResourceAttribute
& MEMORY_ATTRIBUTE_MASK
) == INITIALIZED_MEMORY_ATTRIBUTES
) {
2033 GcdMemoryType
= EfiGcdMemoryTypeReserved
;
2035 if ((ResourceHob
->ResourceAttribute
& MEMORY_ATTRIBUTE_MASK
) == PRESENT_MEMORY_ATTRIBUTES
) {
2036 GcdMemoryType
= EfiGcdMemoryTypeReserved
;
2039 case EFI_RESOURCE_MEMORY_MAPPED_IO
:
2040 case EFI_RESOURCE_FIRMWARE_DEVICE
:
2041 GcdMemoryType
= EfiGcdMemoryTypeMemoryMappedIo
;
2043 case EFI_RESOURCE_MEMORY_MAPPED_IO_PORT
:
2044 case EFI_RESOURCE_MEMORY_RESERVED
:
2045 GcdMemoryType
= EfiGcdMemoryTypeReserved
;
2047 case EFI_RESOURCE_IO
:
2048 GcdIoType
= EfiGcdIoTypeIo
;
2050 case EFI_RESOURCE_IO_RESERVED
:
2051 GcdIoType
= EfiGcdIoTypeReserved
;
2055 if (GcdMemoryType
!= EfiGcdMemoryTypeNonExistent
) {
2057 // Convert the Resource HOB Attributes to an EFI Memory Capabilities mask
2059 Capabilities
= CoreConvertResourceDescriptorHobAttributesToCapabilities (
2061 ResourceHob
->ResourceAttribute
2064 Status
= CoreInternalAddMemorySpace (
2066 ResourceHob
->PhysicalStart
,
2067 ResourceHob
->ResourceLength
,
2072 if (GcdIoType
!= EfiGcdIoTypeNonExistent
) {
2073 Status
= CoreAddIoSpace (
2075 ResourceHob
->PhysicalStart
,
2076 ResourceHob
->ResourceLength
2083 // Allocate first memory region from the GCD by the DXE core
2085 Status
= CoreAllocateMemorySpace (
2086 EfiGcdAllocateAddress
,
2087 EfiGcdMemoryTypeSystemMemory
,
2091 gDxeCoreImageHandle
,
2096 // Walk the HOB list and allocate all memory space that is consumed by memory allocation HOBs,
2097 // and Firmware Volume HOBs. Also update the EFI Memory Map with the memory allocation HOBs.
2099 for (Hob
.Raw
= *HobStart
; !END_OF_HOB_LIST(Hob
); Hob
.Raw
= GET_NEXT_HOB(Hob
)) {
2100 if (GET_HOB_TYPE (Hob
) == EFI_HOB_TYPE_MEMORY_ALLOCATION
) {
2101 MemoryHob
= Hob
.MemoryAllocation
;
2102 BaseAddress
= MemoryHob
->AllocDescriptor
.MemoryBaseAddress
;
2103 Status
= CoreGetMemorySpaceDescriptor (BaseAddress
, &Descriptor
);
2104 if (!EFI_ERROR (Status
)) {
2105 Status
= CoreAllocateMemorySpace (
2106 EfiGcdAllocateAddress
,
2107 Descriptor
.GcdMemoryType
,
2109 MemoryHob
->AllocDescriptor
.MemoryLength
,
2111 gDxeCoreImageHandle
,
2114 if (!EFI_ERROR (Status
) && Descriptor
.GcdMemoryType
== EfiGcdMemoryTypeSystemMemory
) {
2115 CoreAddMemoryDescriptor (
2116 MemoryHob
->AllocDescriptor
.MemoryType
,
2117 MemoryHob
->AllocDescriptor
.MemoryBaseAddress
,
2118 RShiftU64 (MemoryHob
->AllocDescriptor
.MemoryLength
, EFI_PAGE_SHIFT
),
2119 Descriptor
.Capabilities
& (~EFI_MEMORY_RUNTIME
)
2125 if (GET_HOB_TYPE (Hob
) == EFI_HOB_TYPE_FV
) {
2126 FirmwareVolumeHob
= Hob
.FirmwareVolume
;
2127 BaseAddress
= FirmwareVolumeHob
->BaseAddress
;
2128 Status
= CoreAllocateMemorySpace (
2129 EfiGcdAllocateAddress
,
2130 EfiGcdMemoryTypeMemoryMappedIo
,
2132 FirmwareVolumeHob
->Length
,
2134 gDxeCoreImageHandle
,
2141 // Relocate HOB List to an allocated pool buffer.
2143 NewHobList
= AllocateCopyPool (
2144 (UINTN
)PhitHob
->EfiFreeMemoryBottom
- (UINTN
)(*HobStart
),
2147 ASSERT (NewHobList
!= NULL
);
2149 *HobStart
= NewHobList
;
2150 gHobList
= NewHobList
;
2153 // Add and allocate the remaining unallocated system memory to the memory services.
2155 Status
= CoreGetMemorySpaceMap (&NumberOfDescriptors
, &MemorySpaceMap
);
2156 ASSERT (Status
== EFI_SUCCESS
);
2158 for (Index
= 0; Index
< NumberOfDescriptors
; Index
++) {
2159 if (MemorySpaceMap
[Index
].GcdMemoryType
== EfiGcdMemoryTypeSystemMemory
) {
2160 if (MemorySpaceMap
[Index
].ImageHandle
== NULL
) {
2161 BaseAddress
= PageAlignAddress (MemorySpaceMap
[Index
].BaseAddress
);
2162 Length
= PageAlignLength (MemorySpaceMap
[Index
].BaseAddress
+ MemorySpaceMap
[Index
].Length
- BaseAddress
);
2163 if (Length
== 0 || MemorySpaceMap
[Index
].BaseAddress
+ MemorySpaceMap
[Index
].Length
< BaseAddress
) {
2166 CoreAddMemoryDescriptor (
2167 EfiConventionalMemory
,
2169 RShiftU64 (Length
, EFI_PAGE_SHIFT
),
2170 MemorySpaceMap
[Index
].Capabilities
& (~EFI_MEMORY_RUNTIME
)
2172 Status
= CoreAllocateMemorySpace (
2173 EfiGcdAllocateAddress
,
2174 EfiGcdMemoryTypeSystemMemory
,
2178 gDxeCoreImageHandle
,
2184 CoreFreePool (MemorySpaceMap
);