]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Core/Dxe/Gcd/Gcd.c
Updated GCD implementation to consume the correct EFI Resources Attributes(Capabiliti...
[mirror_edk2.git] / MdeModulePkg / Core / Dxe / Gcd / Gcd.c
1 /** @file
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.
5
6 Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.<BR>
7 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
11
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.
14
15 **/
16
17 #include "DxeMain.h"
18 #include "Gcd.h"
19
20 #define MINIMUM_INITIAL_MEMORY_SIZE 0x10000
21
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 )
31
32 #define TESTED_MEMORY_ATTRIBUTES (EFI_RESOURCE_ATTRIBUTE_PRESENT | \
33 EFI_RESOURCE_ATTRIBUTE_INITIALIZED | \
34 EFI_RESOURCE_ATTRIBUTE_TESTED )
35
36 #define INITIALIZED_MEMORY_ATTRIBUTES (EFI_RESOURCE_ATTRIBUTE_PRESENT | \
37 EFI_RESOURCE_ATTRIBUTE_INITIALIZED )
38
39 #define PRESENT_MEMORY_ATTRIBUTES (EFI_RESOURCE_ATTRIBUTE_PRESENT)
40
41 #define INVALID_CPU_ARCH_ATTRIBUTES 0xffffffff
42
43 //
44 // Module Variables
45 //
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);
50
51 EFI_GCD_MAP_ENTRY mGcdMemorySpaceMapEntryTemplate = {
52 EFI_GCD_MAP_SIGNATURE,
53 {
54 NULL,
55 NULL
56 },
57 0,
58 0,
59 0,
60 0,
61 EfiGcdMemoryTypeNonExistent,
62 (EFI_GCD_IO_TYPE) 0,
63 NULL,
64 NULL
65 };
66
67 EFI_GCD_MAP_ENTRY mGcdIoSpaceMapEntryTemplate = {
68 EFI_GCD_MAP_SIGNATURE,
69 {
70 NULL,
71 NULL
72 },
73 0,
74 0,
75 0,
76 0,
77 (EFI_GCD_MEMORY_TYPE) 0,
78 EfiGcdIoTypeNonExistent,
79 NULL,
80 NULL
81 };
82
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_PROTECTABLE, EFI_MEMORY_RP, TRUE },
90 { EFI_RESOURCE_ATTRIBUTE_WRITE_PROTECTABLE, EFI_MEMORY_WP, TRUE },
91 { EFI_RESOURCE_ATTRIBUTE_EXECUTION_PROTECTABLE, 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 },
95 { 0, 0, FALSE }
96 };
97
98 ///
99 /// Lookup table used to print GCD Memory Space Map
100 ///
101 GLOBAL_REMOVE_IF_UNREFERENCED CONST CHAR8 *mGcdMemoryTypeNames[] = {
102 "NonExist ", // EfiGcdMemoryTypeNonExistent
103 "Reserved ", // EfiGcdMemoryTypeReserved
104 "SystemMem", // EfiGcdMemoryTypeSystemMemory
105 "MMIO ", // EfiGcdMemoryTypeMemoryMappedIo
106 "Unknown " // EfiGcdMemoryTypeMaximum
107 };
108
109 ///
110 /// Lookup table used to print GCD I/O Space Map
111 ///
112 GLOBAL_REMOVE_IF_UNREFERENCED CONST CHAR8 *mGcdIoTypeNames[] = {
113 "NonExist", // EfiGcdIoTypeNonExistent
114 "Reserved", // EfiGcdIoTypeReserved
115 "I/O ", // EfiGcdIoTypeIo
116 "Unknown " // EfiGcdIoTypeMaximum
117 };
118
119 ///
120 /// Lookup table used to print GCD Allocation Types
121 ///
122 GLOBAL_REMOVE_IF_UNREFERENCED CONST CHAR8 *mGcdAllocationTypeNames[] = {
123 "AnySearchBottomUp ", // EfiGcdAllocateAnySearchBottomUp
124 "MaxAddressSearchBottomUp ", // EfiGcdAllocateMaxAddressSearchBottomUp
125 "AtAddress ", // EfiGcdAllocateAddress
126 "AnySearchTopDown ", // EfiGcdAllocateAnySearchTopDown
127 "MaxAddressSearchTopDown ", // EfiGcdAllocateMaxAddressSearchTopDown
128 "Unknown " // EfiGcdMaxAllocateType
129 };
130
131 /**
132 Dump the entire contents if the GCD Memory Space Map using DEBUG() macros when
133 PcdDebugPrintErrorLevel has the DEBUG_GCD bit set.
134
135 @param InitialMap TRUE if the initial GCD Memory Map is being dumped. Otherwise, FALSE.
136
137 **/
138 VOID
139 EFIAPI
140 CoreDumpGcdMemorySpaceMap (
141 BOOLEAN InitialMap
142 )
143 {
144 DEBUG_CODE (
145 EFI_STATUS Status;
146 UINTN NumberOfDescriptors;
147 EFI_GCD_MEMORY_SPACE_DESCRIPTOR *MemorySpaceMap;
148 UINTN Index;
149
150 Status = CoreGetMemorySpaceMap (&NumberOfDescriptors, &MemorySpaceMap);
151 ASSERT_EFI_ERROR (Status);
152
153 if (InitialMap) {
154 DEBUG ((DEBUG_GCD, "GCD:Initial GCD Memory Space Map\n"));
155 }
156 DEBUG ((DEBUG_GCD, "GCDMemType Range Capabilities Attributes \n"));
157 DEBUG ((DEBUG_GCD, "========== ================================= ================ ================\n"));
158 for (Index = 0; Index < NumberOfDescriptors; Index++) {
159 DEBUG ((DEBUG_GCD, "%a %016lx-%016lx %016lx %016lx%c\n",
160 mGcdMemoryTypeNames[MIN (MemorySpaceMap[Index].GcdMemoryType, EfiGcdMemoryTypeMaximum)],
161 MemorySpaceMap[Index].BaseAddress,
162 MemorySpaceMap[Index].BaseAddress + MemorySpaceMap[Index].Length - 1,
163 MemorySpaceMap[Index].Capabilities,
164 MemorySpaceMap[Index].Attributes,
165 MemorySpaceMap[Index].ImageHandle == NULL ? ' ' : '*'
166 ));
167 }
168 DEBUG ((DEBUG_GCD, "\n"));
169 FreePool (MemorySpaceMap);
170 );
171 }
172
173 /**
174 Dump the entire contents if the GCD I/O Space Map using DEBUG() macros when
175 PcdDebugPrintErrorLevel has the DEBUG_GCD bit set.
176
177 @param InitialMap TRUE if the initial GCD I/O Map is being dumped. Otherwise, FALSE.
178
179 **/
180 VOID
181 EFIAPI
182 CoreDumpGcdIoSpaceMap (
183 BOOLEAN InitialMap
184 )
185 {
186 DEBUG_CODE (
187 EFI_STATUS Status;
188 UINTN NumberOfDescriptors;
189 EFI_GCD_IO_SPACE_DESCRIPTOR *IoSpaceMap;
190 UINTN Index;
191
192 Status = CoreGetIoSpaceMap (&NumberOfDescriptors, &IoSpaceMap);
193 ASSERT_EFI_ERROR (Status);
194
195 if (InitialMap) {
196 DEBUG ((DEBUG_GCD, "GCD:Initial GCD I/O Space Map\n"));
197 }
198
199 DEBUG ((DEBUG_GCD, "GCDIoType Range \n"));
200 DEBUG ((DEBUG_GCD, "========== =================================\n"));
201 for (Index = 0; Index < NumberOfDescriptors; Index++) {
202 DEBUG ((DEBUG_GCD, "%a %016lx-%016lx%c\n",
203 mGcdIoTypeNames[MIN (IoSpaceMap[Index].GcdIoType, EfiGcdIoTypeMaximum)],
204 IoSpaceMap[Index].BaseAddress,
205 IoSpaceMap[Index].BaseAddress + IoSpaceMap[Index].Length - 1,
206 IoSpaceMap[Index].ImageHandle == NULL ? ' ' : '*'
207 ));
208 }
209 DEBUG ((DEBUG_GCD, "\n"));
210 FreePool (IoSpaceMap);
211 );
212 }
213
214 /**
215 Validate resource descriptor HOB's attributes.
216
217 If Attributes includes some memory resource's settings, it should include
218 the corresponding capabilites also.
219
220 @param Attributes Resource descriptor HOB attributes.
221
222 **/
223 VOID
224 CoreValidateResourceDescriptorHobAttributes (
225 IN UINT64 Attributes
226 )
227 {
228 ASSERT (((Attributes & EFI_RESOURCE_ATTRIBUTE_READ_PROTECTED) == 0) ||
229 ((Attributes & EFI_RESOURCE_ATTRIBUTE_READ_PROTECTABLE) != 0));
230 ASSERT (((Attributes & EFI_RESOURCE_ATTRIBUTE_WRITE_PROTECTED) == 0) ||
231 ((Attributes & EFI_RESOURCE_ATTRIBUTE_WRITE_PROTECTABLE) != 0));
232 ASSERT (((Attributes & EFI_RESOURCE_ATTRIBUTE_EXECUTION_PROTECTED) == 0) ||
233 ((Attributes & EFI_RESOURCE_ATTRIBUTE_EXECUTION_PROTECTABLE) != 0));
234 }
235
236 /**
237 Acquire memory lock on mGcdMemorySpaceLock.
238
239 **/
240 VOID
241 CoreAcquireGcdMemoryLock (
242 VOID
243 )
244 {
245 CoreAcquireLock (&mGcdMemorySpaceLock);
246 }
247
248
249
250 /**
251 Release memory lock on mGcdMemorySpaceLock.
252
253 **/
254 VOID
255 CoreReleaseGcdMemoryLock (
256 VOID
257 )
258 {
259 CoreReleaseLock (&mGcdMemorySpaceLock);
260 }
261
262
263
264 /**
265 Acquire memory lock on mGcdIoSpaceLock.
266
267 **/
268 VOID
269 CoreAcquireGcdIoLock (
270 VOID
271 )
272 {
273 CoreAcquireLock (&mGcdIoSpaceLock);
274 }
275
276
277 /**
278 Release memory lock on mGcdIoSpaceLock.
279
280 **/
281 VOID
282 CoreReleaseGcdIoLock (
283 VOID
284 )
285 {
286 CoreReleaseLock (&mGcdIoSpaceLock);
287 }
288
289
290
291 //
292 // GCD Initialization Worker Functions
293 //
294 /**
295 Aligns a value to the specified boundary.
296
297 @param Value 64 bit value to align
298 @param Alignment Log base 2 of the boundary to align Value to
299 @param RoundUp TRUE if Value is to be rounded up to the nearest
300 aligned boundary. FALSE is Value is to be
301 rounded down to the nearest aligned boundary.
302
303 @return A 64 bit value is the aligned to the value nearest Value with an alignment by Alignment.
304
305 **/
306 UINT64
307 AlignValue (
308 IN UINT64 Value,
309 IN UINTN Alignment,
310 IN BOOLEAN RoundUp
311 )
312 {
313 UINT64 AlignmentMask;
314
315 AlignmentMask = LShiftU64 (1, Alignment) - 1;
316 if (RoundUp) {
317 Value += AlignmentMask;
318 }
319 return Value & (~AlignmentMask);
320 }
321
322
323 /**
324 Aligns address to the page boundary.
325
326 @param Value 64 bit address to align
327
328 @return A 64 bit value is the aligned to the value nearest Value with an alignment by Alignment.
329
330 **/
331 UINT64
332 PageAlignAddress (
333 IN UINT64 Value
334 )
335 {
336 return AlignValue (Value, EFI_PAGE_SHIFT, TRUE);
337 }
338
339
340 /**
341 Aligns length to the page boundary.
342
343 @param Value 64 bit length to align
344
345 @return A 64 bit value is the aligned to the value nearest Value with an alignment by Alignment.
346
347 **/
348 UINT64
349 PageAlignLength (
350 IN UINT64 Value
351 )
352 {
353 return AlignValue (Value, EFI_PAGE_SHIFT, FALSE);
354 }
355
356 //
357 // GCD Memory Space Worker Functions
358 //
359
360 /**
361 Allocate pool for two entries.
362
363 @param TopEntry An entry of GCD map
364 @param BottomEntry An entry of GCD map
365
366 @retval EFI_OUT_OF_RESOURCES No enough buffer to be allocated.
367 @retval EFI_SUCCESS Both entries successfully allocated.
368
369 **/
370 EFI_STATUS
371 CoreAllocateGcdMapEntry (
372 IN OUT EFI_GCD_MAP_ENTRY **TopEntry,
373 IN OUT EFI_GCD_MAP_ENTRY **BottomEntry
374 )
375 {
376 *TopEntry = AllocateZeroPool (sizeof (EFI_GCD_MAP_ENTRY));
377 if (*TopEntry == NULL) {
378 return EFI_OUT_OF_RESOURCES;
379 }
380
381 *BottomEntry = AllocateZeroPool (sizeof (EFI_GCD_MAP_ENTRY));
382 if (*BottomEntry == NULL) {
383 CoreFreePool (*TopEntry);
384 return EFI_OUT_OF_RESOURCES;
385 }
386
387 return EFI_SUCCESS;
388 }
389
390
391 /**
392 Internal function. Inserts a new descriptor into a sorted list
393
394 @param Link The linked list to insert the range BaseAddress
395 and Length into
396 @param Entry A pointer to the entry that is inserted
397 @param BaseAddress The base address of the new range
398 @param Length The length of the new range in bytes
399 @param TopEntry Top pad entry to insert if needed.
400 @param BottomEntry Bottom pad entry to insert if needed.
401
402 @retval EFI_SUCCESS The new range was inserted into the linked list
403
404 **/
405 EFI_STATUS
406 CoreInsertGcdMapEntry (
407 IN LIST_ENTRY *Link,
408 IN EFI_GCD_MAP_ENTRY *Entry,
409 IN EFI_PHYSICAL_ADDRESS BaseAddress,
410 IN UINT64 Length,
411 IN EFI_GCD_MAP_ENTRY *TopEntry,
412 IN EFI_GCD_MAP_ENTRY *BottomEntry
413 )
414 {
415 ASSERT (Length != 0);
416
417 if (BaseAddress > Entry->BaseAddress) {
418 ASSERT (BottomEntry->Signature == 0);
419
420 CopyMem (BottomEntry, Entry, sizeof (EFI_GCD_MAP_ENTRY));
421 Entry->BaseAddress = BaseAddress;
422 BottomEntry->EndAddress = BaseAddress - 1;
423 InsertTailList (Link, &BottomEntry->Link);
424 }
425
426 if ((BaseAddress + Length - 1) < Entry->EndAddress) {
427 ASSERT (TopEntry->Signature == 0);
428
429 CopyMem (TopEntry, Entry, sizeof (EFI_GCD_MAP_ENTRY));
430 TopEntry->BaseAddress = BaseAddress + Length;
431 Entry->EndAddress = BaseAddress + Length - 1;
432 InsertHeadList (Link, &TopEntry->Link);
433 }
434
435 return EFI_SUCCESS;
436 }
437
438
439 /**
440 Merge the Gcd region specified by Link and its adjacent entry.
441
442 @param Link Specify the entry to be merged (with its
443 adjacent entry).
444 @param Forward Direction (forward or backward).
445 @param Map Boundary.
446
447 @retval EFI_SUCCESS Successfully returned.
448 @retval EFI_UNSUPPORTED These adjacent regions could not merge.
449
450 **/
451 EFI_STATUS
452 CoreMergeGcdMapEntry (
453 IN LIST_ENTRY *Link,
454 IN BOOLEAN Forward,
455 IN LIST_ENTRY *Map
456 )
457 {
458 LIST_ENTRY *AdjacentLink;
459 EFI_GCD_MAP_ENTRY *Entry;
460 EFI_GCD_MAP_ENTRY *AdjacentEntry;
461
462 //
463 // Get adjacent entry
464 //
465 if (Forward) {
466 AdjacentLink = Link->ForwardLink;
467 } else {
468 AdjacentLink = Link->BackLink;
469 }
470
471 //
472 // If AdjacentLink is the head of the list, then no merge can be performed
473 //
474 if (AdjacentLink == Map) {
475 return EFI_SUCCESS;
476 }
477
478 Entry = CR (Link, EFI_GCD_MAP_ENTRY, Link, EFI_GCD_MAP_SIGNATURE);
479 AdjacentEntry = CR (AdjacentLink, EFI_GCD_MAP_ENTRY, Link, EFI_GCD_MAP_SIGNATURE);
480
481 if (Entry->Capabilities != AdjacentEntry->Capabilities) {
482 return EFI_UNSUPPORTED;
483 }
484 if (Entry->Attributes != AdjacentEntry->Attributes) {
485 return EFI_UNSUPPORTED;
486 }
487 if (Entry->GcdMemoryType != AdjacentEntry->GcdMemoryType) {
488 return EFI_UNSUPPORTED;
489 }
490 if (Entry->GcdIoType != AdjacentEntry->GcdIoType) {
491 return EFI_UNSUPPORTED;
492 }
493 if (Entry->ImageHandle != AdjacentEntry->ImageHandle) {
494 return EFI_UNSUPPORTED;
495 }
496 if (Entry->DeviceHandle != AdjacentEntry->DeviceHandle) {
497 return EFI_UNSUPPORTED;
498 }
499
500 if (Forward) {
501 Entry->EndAddress = AdjacentEntry->EndAddress;
502 } else {
503 Entry->BaseAddress = AdjacentEntry->BaseAddress;
504 }
505 RemoveEntryList (AdjacentLink);
506 CoreFreePool (AdjacentEntry);
507
508 return EFI_SUCCESS;
509 }
510
511
512 /**
513 Merge adjacent entries on total chain.
514
515 @param TopEntry Top entry of GCD map.
516 @param BottomEntry Bottom entry of GCD map.
517 @param StartLink Start link of the list for this loop.
518 @param EndLink End link of the list for this loop.
519 @param Map Boundary.
520
521 @retval EFI_SUCCESS GCD map successfully cleaned up.
522
523 **/
524 EFI_STATUS
525 CoreCleanupGcdMapEntry (
526 IN EFI_GCD_MAP_ENTRY *TopEntry,
527 IN EFI_GCD_MAP_ENTRY *BottomEntry,
528 IN LIST_ENTRY *StartLink,
529 IN LIST_ENTRY *EndLink,
530 IN LIST_ENTRY *Map
531 )
532 {
533 LIST_ENTRY *Link;
534
535 if (TopEntry->Signature == 0) {
536 CoreFreePool (TopEntry);
537 }
538 if (BottomEntry->Signature == 0) {
539 CoreFreePool (BottomEntry);
540 }
541
542 Link = StartLink;
543 while (Link != EndLink->ForwardLink) {
544 CoreMergeGcdMapEntry (Link, FALSE, Map);
545 Link = Link->ForwardLink;
546 }
547 CoreMergeGcdMapEntry (EndLink, TRUE, Map);
548
549 return EFI_SUCCESS;
550 }
551
552
553 /**
554 Search a segment of memory space in GCD map. The result is a range of GCD entry list.
555
556 @param BaseAddress The start address of the segment.
557 @param Length The length of the segment.
558 @param StartLink The first GCD entry involves this segment of
559 memory space.
560 @param EndLink The first GCD entry involves this segment of
561 memory space.
562 @param Map Points to the start entry to search.
563
564 @retval EFI_SUCCESS Successfully found the entry.
565 @retval EFI_NOT_FOUND Not found.
566
567 **/
568 EFI_STATUS
569 CoreSearchGcdMapEntry (
570 IN EFI_PHYSICAL_ADDRESS BaseAddress,
571 IN UINT64 Length,
572 OUT LIST_ENTRY **StartLink,
573 OUT LIST_ENTRY **EndLink,
574 IN LIST_ENTRY *Map
575 )
576 {
577 LIST_ENTRY *Link;
578 EFI_GCD_MAP_ENTRY *Entry;
579
580 ASSERT (Length != 0);
581
582 *StartLink = NULL;
583 *EndLink = NULL;
584
585 Link = Map->ForwardLink;
586 while (Link != Map) {
587 Entry = CR (Link, EFI_GCD_MAP_ENTRY, Link, EFI_GCD_MAP_SIGNATURE);
588 if (BaseAddress >= Entry->BaseAddress && BaseAddress <= Entry->EndAddress) {
589 *StartLink = Link;
590 }
591 if (*StartLink != NULL) {
592 if ((BaseAddress + Length - 1) >= Entry->BaseAddress &&
593 (BaseAddress + Length - 1) <= Entry->EndAddress ) {
594 *EndLink = Link;
595 return EFI_SUCCESS;
596 }
597 }
598 Link = Link->ForwardLink;
599 }
600
601 return EFI_NOT_FOUND;
602 }
603
604
605 /**
606 Count the amount of GCD map entries.
607
608 @param Map Points to the start entry to do the count loop.
609
610 @return The count.
611
612 **/
613 UINTN
614 CoreCountGcdMapEntry (
615 IN LIST_ENTRY *Map
616 )
617 {
618 UINTN Count;
619 LIST_ENTRY *Link;
620
621 Count = 0;
622 Link = Map->ForwardLink;
623 while (Link != Map) {
624 Count++;
625 Link = Link->ForwardLink;
626 }
627
628 return Count;
629 }
630
631
632
633 /**
634 Return the memory attribute specified by Attributes
635
636 @param Attributes A num with some attribute bits on.
637
638 @return The enum value of memory attribute.
639
640 **/
641 UINT64
642 ConverToCpuArchAttributes (
643 UINT64 Attributes
644 )
645 {
646 if ( (Attributes & EFI_MEMORY_UC) == EFI_MEMORY_UC) {
647 return EFI_MEMORY_UC;
648 }
649
650 if ( (Attributes & EFI_MEMORY_WC ) == EFI_MEMORY_WC) {
651 return EFI_MEMORY_WC;
652 }
653
654 if ( (Attributes & EFI_MEMORY_WT ) == EFI_MEMORY_WT) {
655 return EFI_MEMORY_WT;
656 }
657
658 if ( (Attributes & EFI_MEMORY_WB) == EFI_MEMORY_WB) {
659 return EFI_MEMORY_WB;
660 }
661
662 if ( (Attributes & EFI_MEMORY_WP) == EFI_MEMORY_WP) {
663 return EFI_MEMORY_WP;
664 }
665
666 return INVALID_CPU_ARCH_ATTRIBUTES;
667
668 }
669
670
671 /**
672 Do operation on a segment of memory space specified (add, free, remove, change attribute ...).
673
674 @param Operation The type of the operation
675 @param GcdMemoryType Additional information for the operation
676 @param GcdIoType Additional information for the operation
677 @param BaseAddress Start address of the segment
678 @param Length length of the segment
679 @param Capabilities The alterable attributes of a newly added entry
680 @param Attributes The attributes needs to be set
681
682 @retval EFI_INVALID_PARAMETER Length is 0 or address (length) not aligned when
683 setting attribute.
684 @retval EFI_SUCCESS Action successfully done.
685 @retval EFI_UNSUPPORTED Could not find the proper descriptor on this
686 segment or set an upsupported attribute.
687 @retval EFI_ACCESS_DENIED Operate on an space non-exist or is used for an
688 image.
689 @retval EFI_NOT_FOUND Free a non-using space or remove a non-exist
690 space, and so on.
691 @retval EFI_OUT_OF_RESOURCES No buffer could be allocated.
692
693 **/
694 EFI_STATUS
695 CoreConvertSpace (
696 IN UINTN Operation,
697 IN EFI_GCD_MEMORY_TYPE GcdMemoryType,
698 IN EFI_GCD_IO_TYPE GcdIoType,
699 IN EFI_PHYSICAL_ADDRESS BaseAddress,
700 IN UINT64 Length,
701 IN UINT64 Capabilities,
702 IN UINT64 Attributes
703 )
704 {
705 EFI_STATUS Status;
706 LIST_ENTRY *Map;
707 LIST_ENTRY *Link;
708 EFI_GCD_MAP_ENTRY *Entry;
709 EFI_GCD_MAP_ENTRY *TopEntry;
710 EFI_GCD_MAP_ENTRY *BottomEntry;
711 LIST_ENTRY *StartLink;
712 LIST_ENTRY *EndLink;
713 UINT64 CpuArchAttributes;
714
715 if (Length == 0) {
716 DEBUG ((DEBUG_GCD, " Status = %r\n", EFI_INVALID_PARAMETER));
717 return EFI_INVALID_PARAMETER;
718 }
719
720 Map = NULL;
721 if ((Operation & GCD_MEMORY_SPACE_OPERATION) != 0) {
722 CoreAcquireGcdMemoryLock ();
723 Map = &mGcdMemorySpaceMap;
724 } else if ((Operation & GCD_IO_SPACE_OPERATION) != 0) {
725 CoreAcquireGcdIoLock ();
726 Map = &mGcdIoSpaceMap;
727 } else {
728 ASSERT (FALSE);
729 }
730
731 //
732 // Search for the list of descriptors that cover the range BaseAddress to BaseAddress+Length
733 //
734 Status = CoreSearchGcdMapEntry (BaseAddress, Length, &StartLink, &EndLink, Map);
735 if (EFI_ERROR (Status)) {
736 Status = EFI_UNSUPPORTED;
737
738 goto Done;
739 }
740 ASSERT (StartLink != NULL && EndLink != NULL);
741
742 //
743 // Verify that the list of descriptors are unallocated non-existent memory.
744 //
745 Link = StartLink;
746 while (Link != EndLink->ForwardLink) {
747 Entry = CR (Link, EFI_GCD_MAP_ENTRY, Link, EFI_GCD_MAP_SIGNATURE);
748 switch (Operation) {
749 //
750 // Add operations
751 //
752 case GCD_ADD_MEMORY_OPERATION:
753 if (Entry->GcdMemoryType != EfiGcdMemoryTypeNonExistent ||
754 Entry->ImageHandle != NULL ) {
755 Status = EFI_ACCESS_DENIED;
756 goto Done;
757 }
758 break;
759 case GCD_ADD_IO_OPERATION:
760 if (Entry->GcdIoType != EfiGcdIoTypeNonExistent ||
761 Entry->ImageHandle != NULL ) {
762 Status = EFI_ACCESS_DENIED;
763 goto Done;
764 }
765 break;
766 //
767 // Free operations
768 //
769 case GCD_FREE_MEMORY_OPERATION:
770 case GCD_FREE_IO_OPERATION:
771 if (Entry->ImageHandle == NULL) {
772 Status = EFI_NOT_FOUND;
773 goto Done;
774 }
775 break;
776 //
777 // Remove operations
778 //
779 case GCD_REMOVE_MEMORY_OPERATION:
780 if (Entry->GcdMemoryType == EfiGcdMemoryTypeNonExistent) {
781 Status = EFI_NOT_FOUND;
782 goto Done;
783 }
784 if (Entry->ImageHandle != NULL) {
785 Status = EFI_ACCESS_DENIED;
786 goto Done;
787 }
788 break;
789 case GCD_REMOVE_IO_OPERATION:
790 if (Entry->GcdIoType == EfiGcdIoTypeNonExistent) {
791 Status = EFI_NOT_FOUND;
792 goto Done;
793 }
794 if (Entry->ImageHandle != NULL) {
795 Status = EFI_ACCESS_DENIED;
796 goto Done;
797 }
798 break;
799 //
800 // Set attribute operations
801 //
802 case GCD_SET_ATTRIBUTES_MEMORY_OPERATION:
803 if ((Attributes & EFI_MEMORY_RUNTIME) != 0) {
804 if ((BaseAddress & EFI_PAGE_MASK) != 0 || (Length & EFI_PAGE_MASK) != 0) {
805 Status = EFI_INVALID_PARAMETER;
806 goto Done;
807 }
808 }
809 if ((Entry->Capabilities & Attributes) != Attributes) {
810 Status = EFI_UNSUPPORTED;
811 goto Done;
812 }
813 break;
814 }
815 Link = Link->ForwardLink;
816 }
817
818 //
819 // Allocate work space to perform this operation
820 //
821 Status = CoreAllocateGcdMapEntry (&TopEntry, &BottomEntry);
822 if (EFI_ERROR (Status)) {
823 Status = EFI_OUT_OF_RESOURCES;
824 goto Done;
825 }
826 ASSERT (TopEntry != NULL && BottomEntry != NULL);
827
828 if (Operation == GCD_SET_ATTRIBUTES_MEMORY_OPERATION) {
829 //
830 // Call CPU Arch Protocol to attempt to set attributes on the range
831 //
832 CpuArchAttributes = ConverToCpuArchAttributes (Attributes);
833 if (CpuArchAttributes != INVALID_CPU_ARCH_ATTRIBUTES) {
834 if (gCpu != NULL) {
835 Status = gCpu->SetMemoryAttributes (
836 gCpu,
837 BaseAddress,
838 Length,
839 CpuArchAttributes
840 );
841 if (EFI_ERROR (Status)) {
842 goto Done;
843 }
844 }
845 }
846 }
847
848 //
849 // Convert/Insert the list of descriptors from StartLink to EndLink
850 //
851 Link = StartLink;
852 while (Link != EndLink->ForwardLink) {
853 Entry = CR (Link, EFI_GCD_MAP_ENTRY, Link, EFI_GCD_MAP_SIGNATURE);
854 CoreInsertGcdMapEntry (Link, Entry, BaseAddress, Length, TopEntry, BottomEntry);
855 switch (Operation) {
856 //
857 // Add operations
858 //
859 case GCD_ADD_MEMORY_OPERATION:
860 Entry->GcdMemoryType = GcdMemoryType;
861 if (GcdMemoryType == EfiGcdMemoryTypeMemoryMappedIo) {
862 Entry->Capabilities = Capabilities | EFI_MEMORY_RUNTIME | EFI_MEMORY_PORT_IO;
863 } else {
864 Entry->Capabilities = Capabilities | EFI_MEMORY_RUNTIME;
865 }
866 break;
867 case GCD_ADD_IO_OPERATION:
868 Entry->GcdIoType = GcdIoType;
869 break;
870 //
871 // Free operations
872 //
873 case GCD_FREE_MEMORY_OPERATION:
874 case GCD_FREE_IO_OPERATION:
875 Entry->ImageHandle = NULL;
876 Entry->DeviceHandle = NULL;
877 break;
878 //
879 // Remove operations
880 //
881 case GCD_REMOVE_MEMORY_OPERATION:
882 Entry->GcdMemoryType = EfiGcdMemoryTypeNonExistent;
883 Entry->Capabilities = 0;
884 break;
885 case GCD_REMOVE_IO_OPERATION:
886 Entry->GcdIoType = EfiGcdIoTypeNonExistent;
887 break;
888 //
889 // Set attribute operations
890 //
891 case GCD_SET_ATTRIBUTES_MEMORY_OPERATION:
892 Entry->Attributes = Attributes;
893 break;
894 }
895 Link = Link->ForwardLink;
896 }
897
898 //
899 // Cleanup
900 //
901 Status = CoreCleanupGcdMapEntry (TopEntry, BottomEntry, StartLink, EndLink, Map);
902
903 Done:
904 DEBUG ((DEBUG_GCD, " Status = %r\n", Status));
905
906 if ((Operation & GCD_MEMORY_SPACE_OPERATION) != 0) {
907 CoreReleaseGcdMemoryLock ();
908 CoreDumpGcdMemorySpaceMap (FALSE);
909 }
910 if ((Operation & GCD_IO_SPACE_OPERATION) != 0) {
911 CoreReleaseGcdIoLock ();
912 CoreDumpGcdIoSpaceMap (FALSE);
913 }
914
915 return Status;
916 }
917
918
919 /**
920 Check whether an entry could be used to allocate space.
921
922 @param Operation Allocate memory or IO
923 @param Entry The entry to be tested
924 @param GcdMemoryType The desired memory type
925 @param GcdIoType The desired IO type
926
927 @retval EFI_NOT_FOUND The memory type does not match or there's an
928 image handle on the entry.
929 @retval EFI_UNSUPPORTED The operation unsupported.
930 @retval EFI_SUCCESS It's ok for this entry to be used to allocate
931 space.
932
933 **/
934 EFI_STATUS
935 CoreAllocateSpaceCheckEntry (
936 IN UINTN Operation,
937 IN EFI_GCD_MAP_ENTRY *Entry,
938 IN EFI_GCD_MEMORY_TYPE GcdMemoryType,
939 IN EFI_GCD_IO_TYPE GcdIoType
940 )
941 {
942 if (Entry->ImageHandle != NULL) {
943 return EFI_NOT_FOUND;
944 }
945 switch (Operation) {
946 case GCD_ALLOCATE_MEMORY_OPERATION:
947 if (Entry->GcdMemoryType != GcdMemoryType) {
948 return EFI_NOT_FOUND;
949 }
950 break;
951 case GCD_ALLOCATE_IO_OPERATION:
952 if (Entry->GcdIoType != GcdIoType) {
953 return EFI_NOT_FOUND;
954 }
955 break;
956 default:
957 return EFI_UNSUPPORTED;
958 }
959 return EFI_SUCCESS;
960 }
961
962
963 /**
964 Allocate space on specified address and length.
965
966 @param Operation The type of operation (memory or IO)
967 @param GcdAllocateType The type of allocate operation
968 @param GcdMemoryType The desired memory type
969 @param GcdIoType The desired IO type
970 @param Alignment Align with 2^Alignment
971 @param Length Length to allocate
972 @param BaseAddress Base address to allocate
973 @param ImageHandle The image handle consume the allocated space.
974 @param DeviceHandle The device handle consume the allocated space.
975
976 @retval EFI_INVALID_PARAMETER Invalid parameter.
977 @retval EFI_NOT_FOUND No descriptor for the desired space exists.
978 @retval EFI_SUCCESS Space successfully allocated.
979
980 **/
981 EFI_STATUS
982 CoreAllocateSpace (
983 IN UINTN Operation,
984 IN EFI_GCD_ALLOCATE_TYPE GcdAllocateType,
985 IN EFI_GCD_MEMORY_TYPE GcdMemoryType,
986 IN EFI_GCD_IO_TYPE GcdIoType,
987 IN UINTN Alignment,
988 IN UINT64 Length,
989 IN OUT EFI_PHYSICAL_ADDRESS *BaseAddress,
990 IN EFI_HANDLE ImageHandle,
991 IN EFI_HANDLE DeviceHandle OPTIONAL
992 )
993 {
994 EFI_STATUS Status;
995 EFI_PHYSICAL_ADDRESS AlignmentMask;
996 EFI_PHYSICAL_ADDRESS MaxAddress;
997 LIST_ENTRY *Map;
998 LIST_ENTRY *Link;
999 LIST_ENTRY *SubLink;
1000 EFI_GCD_MAP_ENTRY *Entry;
1001 EFI_GCD_MAP_ENTRY *TopEntry;
1002 EFI_GCD_MAP_ENTRY *BottomEntry;
1003 LIST_ENTRY *StartLink;
1004 LIST_ENTRY *EndLink;
1005 BOOLEAN Found;
1006
1007 //
1008 // Make sure parameters are valid
1009 //
1010 if (GcdAllocateType < 0 || GcdAllocateType >= EfiGcdMaxAllocateType) {
1011 DEBUG ((DEBUG_GCD, " Status = %r\n", EFI_INVALID_PARAMETER));
1012 return EFI_INVALID_PARAMETER;
1013 }
1014 if (GcdMemoryType < 0 || GcdMemoryType >= EfiGcdMemoryTypeMaximum) {
1015 DEBUG ((DEBUG_GCD, " Status = %r\n", EFI_INVALID_PARAMETER));
1016 return EFI_INVALID_PARAMETER;
1017 }
1018 if (GcdIoType < 0 || GcdIoType >= EfiGcdIoTypeMaximum) {
1019 DEBUG ((DEBUG_GCD, " Status = %r\n", EFI_INVALID_PARAMETER));
1020 return EFI_INVALID_PARAMETER;
1021 }
1022 if (BaseAddress == NULL) {
1023 DEBUG ((DEBUG_GCD, " Status = %r\n", EFI_INVALID_PARAMETER));
1024 return EFI_INVALID_PARAMETER;
1025 }
1026 if (ImageHandle == NULL) {
1027 DEBUG ((DEBUG_GCD, " Status = %r\n", EFI_INVALID_PARAMETER));
1028 return EFI_INVALID_PARAMETER;
1029 }
1030 if (Alignment >= 64) {
1031 DEBUG ((DEBUG_GCD, " Status = %r\n", EFI_NOT_FOUND));
1032 return EFI_NOT_FOUND;
1033 }
1034 if (Length == 0) {
1035 DEBUG ((DEBUG_GCD, " Status = %r\n", EFI_INVALID_PARAMETER));
1036 return EFI_INVALID_PARAMETER;
1037 }
1038
1039 Map = NULL;
1040 if ((Operation & GCD_MEMORY_SPACE_OPERATION) != 0) {
1041 CoreAcquireGcdMemoryLock ();
1042 Map = &mGcdMemorySpaceMap;
1043 } else if ((Operation & GCD_IO_SPACE_OPERATION) != 0) {
1044 CoreAcquireGcdIoLock ();
1045 Map = &mGcdIoSpaceMap;
1046 } else {
1047 ASSERT (FALSE);
1048 }
1049
1050 Found = FALSE;
1051 StartLink = NULL;
1052 EndLink = NULL;
1053 //
1054 // Compute alignment bit mask
1055 //
1056 AlignmentMask = LShiftU64 (1, Alignment) - 1;
1057
1058 if (GcdAllocateType == EfiGcdAllocateAddress) {
1059 //
1060 // Verify that the BaseAddress passed in is aligned correctly
1061 //
1062 if ((*BaseAddress & AlignmentMask) != 0) {
1063 Status = EFI_NOT_FOUND;
1064 goto Done;
1065 }
1066
1067 //
1068 // Search for the list of descriptors that cover the range BaseAddress to BaseAddress+Length
1069 //
1070 Status = CoreSearchGcdMapEntry (*BaseAddress, Length, &StartLink, &EndLink, Map);
1071 if (EFI_ERROR (Status)) {
1072 Status = EFI_NOT_FOUND;
1073 goto Done;
1074 }
1075 ASSERT (StartLink != NULL && EndLink != NULL);
1076
1077 //
1078 // Verify that the list of descriptors are unallocated memory matching GcdMemoryType.
1079 //
1080 Link = StartLink;
1081 while (Link != EndLink->ForwardLink) {
1082 Entry = CR (Link, EFI_GCD_MAP_ENTRY, Link, EFI_GCD_MAP_SIGNATURE);
1083 Link = Link->ForwardLink;
1084 Status = CoreAllocateSpaceCheckEntry (Operation, Entry, GcdMemoryType, GcdIoType);
1085 if (EFI_ERROR (Status)) {
1086 goto Done;
1087 }
1088 }
1089 Found = TRUE;
1090 } else {
1091
1092 Entry = CR (Map->BackLink, EFI_GCD_MAP_ENTRY, Link, EFI_GCD_MAP_SIGNATURE);
1093
1094 //
1095 // Compute the maximum address to use in the search algorithm
1096 //
1097 if (GcdAllocateType == EfiGcdAllocateMaxAddressSearchBottomUp ||
1098 GcdAllocateType == EfiGcdAllocateMaxAddressSearchTopDown ) {
1099 MaxAddress = *BaseAddress;
1100 } else {
1101 MaxAddress = Entry->EndAddress;
1102 }
1103
1104 //
1105 // Verify that the list of descriptors are unallocated memory matching GcdMemoryType.
1106 //
1107 if (GcdAllocateType == EfiGcdAllocateMaxAddressSearchTopDown ||
1108 GcdAllocateType == EfiGcdAllocateAnySearchTopDown ) {
1109 Link = Map->BackLink;
1110 } else {
1111 Link = Map->ForwardLink;
1112 }
1113 while (Link != Map) {
1114 Entry = CR (Link, EFI_GCD_MAP_ENTRY, Link, EFI_GCD_MAP_SIGNATURE);
1115
1116 if (GcdAllocateType == EfiGcdAllocateMaxAddressSearchTopDown ||
1117 GcdAllocateType == EfiGcdAllocateAnySearchTopDown ) {
1118 Link = Link->BackLink;
1119 } else {
1120 Link = Link->ForwardLink;
1121 }
1122
1123 Status = CoreAllocateSpaceCheckEntry (Operation, Entry, GcdMemoryType, GcdIoType);
1124 if (EFI_ERROR (Status)) {
1125 continue;
1126 }
1127
1128 if (GcdAllocateType == EfiGcdAllocateMaxAddressSearchTopDown ||
1129 GcdAllocateType == EfiGcdAllocateAnySearchTopDown) {
1130 if ((Entry->BaseAddress + Length) > MaxAddress) {
1131 continue;
1132 }
1133 if (Length > (Entry->EndAddress + 1)) {
1134 Status = EFI_NOT_FOUND;
1135 goto Done;
1136 }
1137 if (Entry->EndAddress > MaxAddress) {
1138 *BaseAddress = MaxAddress;
1139 } else {
1140 *BaseAddress = Entry->EndAddress;
1141 }
1142 *BaseAddress = (*BaseAddress + 1 - Length) & (~AlignmentMask);
1143 } else {
1144 *BaseAddress = (Entry->BaseAddress + AlignmentMask) & (~AlignmentMask);
1145 if ((*BaseAddress + Length - 1) > MaxAddress) {
1146 Status = EFI_NOT_FOUND;
1147 goto Done;
1148 }
1149 }
1150
1151 //
1152 // Search for the list of descriptors that cover the range BaseAddress to BaseAddress+Length
1153 //
1154 Status = CoreSearchGcdMapEntry (*BaseAddress, Length, &StartLink, &EndLink, Map);
1155 if (EFI_ERROR (Status)) {
1156 Status = EFI_NOT_FOUND;
1157 goto Done;
1158 }
1159 ASSERT (StartLink != NULL && EndLink != NULL);
1160
1161 Link = StartLink;
1162 //
1163 // Verify that the list of descriptors are unallocated memory matching GcdMemoryType.
1164 //
1165 Found = TRUE;
1166 SubLink = StartLink;
1167 while (SubLink != EndLink->ForwardLink) {
1168 Entry = CR (SubLink, EFI_GCD_MAP_ENTRY, Link, EFI_GCD_MAP_SIGNATURE);
1169 Status = CoreAllocateSpaceCheckEntry (Operation, Entry, GcdMemoryType, GcdIoType);
1170 if (EFI_ERROR (Status)) {
1171 Link = SubLink;
1172 Found = FALSE;
1173 break;
1174 }
1175 SubLink = SubLink->ForwardLink;
1176 }
1177 if (Found) {
1178 break;
1179 }
1180 }
1181 }
1182 if (!Found) {
1183 Status = EFI_NOT_FOUND;
1184 goto Done;
1185 }
1186
1187 //
1188 // Allocate work space to perform this operation
1189 //
1190 Status = CoreAllocateGcdMapEntry (&TopEntry, &BottomEntry);
1191 if (EFI_ERROR (Status)) {
1192 Status = EFI_OUT_OF_RESOURCES;
1193 goto Done;
1194 }
1195 ASSERT (TopEntry != NULL && BottomEntry != NULL);
1196
1197 //
1198 // Convert/Insert the list of descriptors from StartLink to EndLink
1199 //
1200 Link = StartLink;
1201 while (Link != EndLink->ForwardLink) {
1202 Entry = CR (Link, EFI_GCD_MAP_ENTRY, Link, EFI_GCD_MAP_SIGNATURE);
1203 CoreInsertGcdMapEntry (Link, Entry, *BaseAddress, Length, TopEntry, BottomEntry);
1204 Entry->ImageHandle = ImageHandle;
1205 Entry->DeviceHandle = DeviceHandle;
1206 Link = Link->ForwardLink;
1207 }
1208
1209 //
1210 // Cleanup
1211 //
1212 Status = CoreCleanupGcdMapEntry (TopEntry, BottomEntry, StartLink, EndLink, Map);
1213
1214 Done:
1215 DEBUG ((DEBUG_GCD, " Status = %r", Status));
1216 if (!EFI_ERROR (Status)) {
1217 DEBUG ((DEBUG_GCD, " (BaseAddress = %016lx)", *BaseAddress));
1218 }
1219 DEBUG ((DEBUG_GCD, "\n"));
1220
1221 if ((Operation & GCD_MEMORY_SPACE_OPERATION) != 0) {
1222 CoreReleaseGcdMemoryLock ();
1223 CoreDumpGcdMemorySpaceMap (FALSE);
1224 }
1225 if ((Operation & GCD_IO_SPACE_OPERATION) !=0) {
1226 CoreReleaseGcdIoLock ();
1227 CoreDumpGcdIoSpaceMap (FALSE);
1228 }
1229
1230 return Status;
1231 }
1232
1233
1234 /**
1235 Add a segment of memory to GCD map.
1236
1237 @param GcdMemoryType Memory type of the segment.
1238 @param BaseAddress Base address of the segment.
1239 @param Length Length of the segment.
1240 @param Capabilities alterable attributes of the segment.
1241
1242 @retval EFI_INVALID_PARAMETER Invalid parameters.
1243 @retval EFI_SUCCESS Successfully add a segment of memory space.
1244
1245 **/
1246 EFI_STATUS
1247 CoreInternalAddMemorySpace (
1248 IN EFI_GCD_MEMORY_TYPE GcdMemoryType,
1249 IN EFI_PHYSICAL_ADDRESS BaseAddress,
1250 IN UINT64 Length,
1251 IN UINT64 Capabilities
1252 )
1253 {
1254 DEBUG ((DEBUG_GCD, "GCD:AddMemorySpace(Base=%016lx,Length=%016lx)\n", BaseAddress, Length));
1255 DEBUG ((DEBUG_GCD, " GcdMemoryType = %a\n", mGcdMemoryTypeNames[MIN (GcdMemoryType, EfiGcdMemoryTypeMaximum)]));
1256 DEBUG ((DEBUG_GCD, " Capabilities = %016lx\n", Capabilities));
1257
1258 //
1259 // Make sure parameters are valid
1260 //
1261 if (GcdMemoryType <= EfiGcdMemoryTypeNonExistent || GcdMemoryType >= EfiGcdMemoryTypeMaximum) {
1262 return EFI_INVALID_PARAMETER;
1263 }
1264
1265 return CoreConvertSpace (GCD_ADD_MEMORY_OPERATION, GcdMemoryType, (EFI_GCD_IO_TYPE) 0, BaseAddress, Length, Capabilities, 0);
1266 }
1267
1268 //
1269 // GCD Core Services
1270 //
1271
1272 /**
1273 Allocates nonexistent memory, reserved memory, system memory, or memorymapped
1274 I/O resources from the global coherency domain of the processor.
1275
1276 @param GcdAllocateType The type of allocate operation
1277 @param GcdMemoryType The desired memory type
1278 @param Alignment Align with 2^Alignment
1279 @param Length Length to allocate
1280 @param BaseAddress Base address to allocate
1281 @param ImageHandle The image handle consume the allocated space.
1282 @param DeviceHandle The device handle consume the allocated space.
1283
1284 @retval EFI_INVALID_PARAMETER Invalid parameter.
1285 @retval EFI_NOT_FOUND No descriptor contains the desired space.
1286 @retval EFI_SUCCESS Memory space successfully allocated.
1287
1288 **/
1289 EFI_STATUS
1290 EFIAPI
1291 CoreAllocateMemorySpace (
1292 IN EFI_GCD_ALLOCATE_TYPE GcdAllocateType,
1293 IN EFI_GCD_MEMORY_TYPE GcdMemoryType,
1294 IN UINTN Alignment,
1295 IN UINT64 Length,
1296 IN OUT EFI_PHYSICAL_ADDRESS *BaseAddress,
1297 IN EFI_HANDLE ImageHandle,
1298 IN EFI_HANDLE DeviceHandle OPTIONAL
1299 )
1300 {
1301 DEBUG ((DEBUG_GCD, "GCD:AllocateMemorySpace(Base=%016lx,Length=%016lx)\n", *BaseAddress, Length));
1302 DEBUG ((DEBUG_GCD, " GcdAllocateType = %a\n", mGcdAllocationTypeNames[MIN (GcdAllocateType, EfiGcdMaxAllocateType)]));
1303 DEBUG ((DEBUG_GCD, " GcdMemoryType = %a\n", mGcdMemoryTypeNames[MIN (GcdMemoryType, EfiGcdMemoryTypeMaximum)]));
1304 DEBUG ((DEBUG_GCD, " Alignment = %016lx\n", LShiftU64 (1, Alignment)));
1305 DEBUG ((DEBUG_GCD, " ImageHandle = %p\n", ImageHandle));
1306 DEBUG ((DEBUG_GCD, " DeviceHandle = %p\n", DeviceHandle));
1307
1308 return CoreAllocateSpace (
1309 GCD_ALLOCATE_MEMORY_OPERATION,
1310 GcdAllocateType,
1311 GcdMemoryType,
1312 (EFI_GCD_IO_TYPE) 0,
1313 Alignment,
1314 Length,
1315 BaseAddress,
1316 ImageHandle,
1317 DeviceHandle
1318 );
1319 }
1320
1321
1322 /**
1323 Adds reserved memory, system memory, or memory-mapped I/O resources to the
1324 global coherency domain of the processor.
1325
1326 @param GcdMemoryType Memory type of the memory space.
1327 @param BaseAddress Base address of the memory space.
1328 @param Length Length of the memory space.
1329 @param Capabilities alterable attributes of the memory space.
1330
1331 @retval EFI_SUCCESS Merged this memory space into GCD map.
1332
1333 **/
1334 EFI_STATUS
1335 EFIAPI
1336 CoreAddMemorySpace (
1337 IN EFI_GCD_MEMORY_TYPE GcdMemoryType,
1338 IN EFI_PHYSICAL_ADDRESS BaseAddress,
1339 IN UINT64 Length,
1340 IN UINT64 Capabilities
1341 )
1342 {
1343 EFI_STATUS Status;
1344 EFI_PHYSICAL_ADDRESS PageBaseAddress;
1345 UINT64 PageLength;
1346
1347 Status = CoreInternalAddMemorySpace (GcdMemoryType, BaseAddress, Length, Capabilities);
1348
1349 if (!EFI_ERROR (Status) && GcdMemoryType == EfiGcdMemoryTypeSystemMemory) {
1350
1351 PageBaseAddress = PageAlignLength (BaseAddress);
1352 PageLength = PageAlignLength (BaseAddress + Length - PageBaseAddress);
1353
1354 Status = CoreAllocateMemorySpace (
1355 EfiGcdAllocateAddress,
1356 GcdMemoryType,
1357 EFI_PAGE_SHIFT,
1358 PageLength,
1359 &PageBaseAddress,
1360 gDxeCoreImageHandle,
1361 NULL
1362 );
1363
1364 if (!EFI_ERROR (Status)) {
1365 CoreAddMemoryDescriptor (
1366 EfiConventionalMemory,
1367 PageBaseAddress,
1368 RShiftU64 (PageLength, EFI_PAGE_SHIFT),
1369 Capabilities
1370 );
1371 } else {
1372 for (; PageLength != 0; PageLength -= EFI_PAGE_SIZE, PageBaseAddress += EFI_PAGE_SIZE) {
1373 Status = CoreAllocateMemorySpace (
1374 EfiGcdAllocateAddress,
1375 GcdMemoryType,
1376 EFI_PAGE_SHIFT,
1377 EFI_PAGE_SIZE,
1378 &PageBaseAddress,
1379 gDxeCoreImageHandle,
1380 NULL
1381 );
1382
1383 if (!EFI_ERROR (Status)) {
1384 CoreAddMemoryDescriptor (
1385 EfiConventionalMemory,
1386 PageBaseAddress,
1387 1,
1388 Capabilities
1389 );
1390 }
1391 }
1392 }
1393 }
1394 return Status;
1395 }
1396
1397
1398 /**
1399 Frees nonexistent memory, reserved memory, system memory, or memory-mapped
1400 I/O resources from the global coherency domain of the processor.
1401
1402 @param BaseAddress Base address of the memory space.
1403 @param Length Length of the memory space.
1404
1405 @retval EFI_SUCCESS Space successfully freed.
1406
1407 **/
1408 EFI_STATUS
1409 EFIAPI
1410 CoreFreeMemorySpace (
1411 IN EFI_PHYSICAL_ADDRESS BaseAddress,
1412 IN UINT64 Length
1413 )
1414 {
1415 DEBUG ((DEBUG_GCD, "GCD:FreeMemorySpace(Base=%016lx,Length=%016lx)\n", BaseAddress, Length));
1416
1417 return CoreConvertSpace (GCD_FREE_MEMORY_OPERATION, (EFI_GCD_MEMORY_TYPE) 0, (EFI_GCD_IO_TYPE) 0, BaseAddress, Length, 0, 0);
1418 }
1419
1420
1421 /**
1422 Removes reserved memory, system memory, or memory-mapped I/O resources from
1423 the global coherency domain of the processor.
1424
1425 @param BaseAddress Base address of the memory space.
1426 @param Length Length of the memory space.
1427
1428 @retval EFI_SUCCESS Successfully remove a segment of memory space.
1429
1430 **/
1431 EFI_STATUS
1432 EFIAPI
1433 CoreRemoveMemorySpace (
1434 IN EFI_PHYSICAL_ADDRESS BaseAddress,
1435 IN UINT64 Length
1436 )
1437 {
1438 DEBUG ((DEBUG_GCD, "GCD:RemoveMemorySpace(Base=%016lx,Length=%016lx)\n", BaseAddress, Length));
1439
1440 return CoreConvertSpace (GCD_REMOVE_MEMORY_OPERATION, (EFI_GCD_MEMORY_TYPE) 0, (EFI_GCD_IO_TYPE) 0, BaseAddress, Length, 0, 0);
1441 }
1442
1443
1444 /**
1445 Build a memory descriptor according to an entry.
1446
1447 @param Descriptor The descriptor to be built
1448 @param Entry According to this entry
1449
1450 **/
1451 VOID
1452 BuildMemoryDescriptor (
1453 IN OUT EFI_GCD_MEMORY_SPACE_DESCRIPTOR *Descriptor,
1454 IN EFI_GCD_MAP_ENTRY *Entry
1455 )
1456 {
1457 Descriptor->BaseAddress = Entry->BaseAddress;
1458 Descriptor->Length = Entry->EndAddress - Entry->BaseAddress + 1;
1459 Descriptor->Capabilities = Entry->Capabilities;
1460 Descriptor->Attributes = Entry->Attributes;
1461 Descriptor->GcdMemoryType = Entry->GcdMemoryType;
1462 Descriptor->ImageHandle = Entry->ImageHandle;
1463 Descriptor->DeviceHandle = Entry->DeviceHandle;
1464 }
1465
1466
1467 /**
1468 Retrieves the descriptor for a memory region containing a specified address.
1469
1470 @param BaseAddress Specified start address
1471 @param Descriptor Specified length
1472
1473 @retval EFI_INVALID_PARAMETER Invalid parameter
1474 @retval EFI_SUCCESS Successfully get memory space descriptor.
1475
1476 **/
1477 EFI_STATUS
1478 EFIAPI
1479 CoreGetMemorySpaceDescriptor (
1480 IN EFI_PHYSICAL_ADDRESS BaseAddress,
1481 OUT EFI_GCD_MEMORY_SPACE_DESCRIPTOR *Descriptor
1482 )
1483 {
1484 EFI_STATUS Status;
1485 LIST_ENTRY *StartLink;
1486 LIST_ENTRY *EndLink;
1487 EFI_GCD_MAP_ENTRY *Entry;
1488
1489 //
1490 // Make sure parameters are valid
1491 //
1492 if (Descriptor == NULL) {
1493 return EFI_INVALID_PARAMETER;
1494 }
1495
1496 CoreAcquireGcdMemoryLock ();
1497
1498 //
1499 // Search for the list of descriptors that contain BaseAddress
1500 //
1501 Status = CoreSearchGcdMapEntry (BaseAddress, 1, &StartLink, &EndLink, &mGcdMemorySpaceMap);
1502 if (EFI_ERROR (Status)) {
1503 Status = EFI_NOT_FOUND;
1504 } else {
1505 ASSERT (StartLink != NULL && EndLink != NULL);
1506 //
1507 // Copy the contents of the found descriptor into Descriptor
1508 //
1509 Entry = CR (StartLink, EFI_GCD_MAP_ENTRY, Link, EFI_GCD_MAP_SIGNATURE);
1510 BuildMemoryDescriptor (Descriptor, Entry);
1511 }
1512
1513 CoreReleaseGcdMemoryLock ();
1514
1515 return Status;
1516 }
1517
1518
1519 /**
1520 Modifies the attributes for a memory region in the global coherency domain of the
1521 processor.
1522
1523 @param BaseAddress Specified start address
1524 @param Length Specified length
1525 @param Attributes Specified attributes
1526
1527 @retval EFI_SUCCESS Successfully set attribute of a segment of
1528 memory space.
1529
1530 **/
1531 EFI_STATUS
1532 EFIAPI
1533 CoreSetMemorySpaceAttributes (
1534 IN EFI_PHYSICAL_ADDRESS BaseAddress,
1535 IN UINT64 Length,
1536 IN UINT64 Attributes
1537 )
1538 {
1539 DEBUG ((DEBUG_GCD, "GCD:SetMemorySpaceAttributes(Base=%016lx,Length=%016lx)\n", BaseAddress, Length));
1540 DEBUG ((DEBUG_GCD, " Attributes = %016lx\n", Attributes));
1541
1542 return CoreConvertSpace (GCD_SET_ATTRIBUTES_MEMORY_OPERATION, (EFI_GCD_MEMORY_TYPE) 0, (EFI_GCD_IO_TYPE) 0, BaseAddress, Length, 0, Attributes);
1543 }
1544
1545
1546 /**
1547 Returns a map of the memory resources in the global coherency domain of the
1548 processor.
1549
1550 @param NumberOfDescriptors Number of descriptors.
1551 @param MemorySpaceMap Descriptor array
1552
1553 @retval EFI_INVALID_PARAMETER Invalid parameter
1554 @retval EFI_OUT_OF_RESOURCES No enough buffer to allocate
1555 @retval EFI_SUCCESS Successfully get memory space map.
1556
1557 **/
1558 EFI_STATUS
1559 EFIAPI
1560 CoreGetMemorySpaceMap (
1561 OUT UINTN *NumberOfDescriptors,
1562 OUT EFI_GCD_MEMORY_SPACE_DESCRIPTOR **MemorySpaceMap
1563 )
1564 {
1565 EFI_STATUS Status;
1566 LIST_ENTRY *Link;
1567 EFI_GCD_MAP_ENTRY *Entry;
1568 EFI_GCD_MEMORY_SPACE_DESCRIPTOR *Descriptor;
1569
1570 //
1571 // Make sure parameters are valid
1572 //
1573 if (NumberOfDescriptors == NULL) {
1574 return EFI_INVALID_PARAMETER;
1575 }
1576 if (MemorySpaceMap == NULL) {
1577 return EFI_INVALID_PARAMETER;
1578 }
1579
1580 CoreAcquireGcdMemoryLock ();
1581
1582 //
1583 // Count the number of descriptors
1584 //
1585 *NumberOfDescriptors = CoreCountGcdMapEntry (&mGcdMemorySpaceMap);
1586
1587 //
1588 // Allocate the MemorySpaceMap
1589 //
1590 *MemorySpaceMap = AllocatePool (*NumberOfDescriptors * sizeof (EFI_GCD_MEMORY_SPACE_DESCRIPTOR));
1591 if (*MemorySpaceMap == NULL) {
1592 Status = EFI_OUT_OF_RESOURCES;
1593 goto Done;
1594 }
1595
1596 //
1597 // Fill in the MemorySpaceMap
1598 //
1599 Descriptor = *MemorySpaceMap;
1600 Link = mGcdMemorySpaceMap.ForwardLink;
1601 while (Link != &mGcdMemorySpaceMap) {
1602 Entry = CR (Link, EFI_GCD_MAP_ENTRY, Link, EFI_GCD_MAP_SIGNATURE);
1603 BuildMemoryDescriptor (Descriptor, Entry);
1604 Descriptor++;
1605 Link = Link->ForwardLink;
1606 }
1607 Status = EFI_SUCCESS;
1608
1609 Done:
1610 CoreReleaseGcdMemoryLock ();
1611 return Status;
1612 }
1613
1614
1615 /**
1616 Adds reserved I/O or I/O resources to the global coherency domain of the processor.
1617
1618 @param GcdIoType IO type of the segment.
1619 @param BaseAddress Base address of the segment.
1620 @param Length Length of the segment.
1621
1622 @retval EFI_SUCCESS Merged this segment into GCD map.
1623 @retval EFI_INVALID_PARAMETER Parameter not valid
1624
1625 **/
1626 EFI_STATUS
1627 EFIAPI
1628 CoreAddIoSpace (
1629 IN EFI_GCD_IO_TYPE GcdIoType,
1630 IN EFI_PHYSICAL_ADDRESS BaseAddress,
1631 IN UINT64 Length
1632 )
1633 {
1634 DEBUG ((DEBUG_GCD, "GCD:AddIoSpace(Base=%016lx,Length=%016lx)\n", BaseAddress, Length));
1635 DEBUG ((DEBUG_GCD, " GcdIoType = %a\n", mGcdIoTypeNames[MIN (GcdIoType, EfiGcdIoTypeMaximum)]));
1636
1637 //
1638 // Make sure parameters are valid
1639 //
1640 if (GcdIoType <= EfiGcdIoTypeNonExistent || GcdIoType >= EfiGcdIoTypeMaximum) {
1641 return EFI_INVALID_PARAMETER;
1642 }
1643 return CoreConvertSpace (GCD_ADD_IO_OPERATION, (EFI_GCD_MEMORY_TYPE) 0, GcdIoType, BaseAddress, Length, 0, 0);
1644 }
1645
1646
1647 /**
1648 Allocates nonexistent I/O, reserved I/O, or I/O resources from the global coherency
1649 domain of the processor.
1650
1651 @param GcdAllocateType The type of allocate operation
1652 @param GcdIoType The desired IO type
1653 @param Alignment Align with 2^Alignment
1654 @param Length Length to allocate
1655 @param BaseAddress Base address to allocate
1656 @param ImageHandle The image handle consume the allocated space.
1657 @param DeviceHandle The device handle consume the allocated space.
1658
1659 @retval EFI_INVALID_PARAMETER Invalid parameter.
1660 @retval EFI_NOT_FOUND No descriptor contains the desired space.
1661 @retval EFI_SUCCESS IO space successfully allocated.
1662
1663 **/
1664 EFI_STATUS
1665 EFIAPI
1666 CoreAllocateIoSpace (
1667 IN EFI_GCD_ALLOCATE_TYPE GcdAllocateType,
1668 IN EFI_GCD_IO_TYPE GcdIoType,
1669 IN UINTN Alignment,
1670 IN UINT64 Length,
1671 IN OUT EFI_PHYSICAL_ADDRESS *BaseAddress,
1672 IN EFI_HANDLE ImageHandle,
1673 IN EFI_HANDLE DeviceHandle OPTIONAL
1674 )
1675 {
1676 DEBUG ((DEBUG_GCD, "GCD:AllocateIoSpace(Base=%016lx,Length=%016lx)\n", *BaseAddress, Length));
1677 DEBUG ((DEBUG_GCD, " GcdAllocateType = %a\n", mGcdAllocationTypeNames[MIN (GcdAllocateType, EfiGcdMaxAllocateType)]));
1678 DEBUG ((DEBUG_GCD, " GcdIoType = %a\n", mGcdIoTypeNames[MIN (GcdIoType, EfiGcdIoTypeMaximum)]));
1679 DEBUG ((DEBUG_GCD, " Alignment = %016lx\n", LShiftU64 (1, Alignment)));
1680 DEBUG ((DEBUG_GCD, " ImageHandle = %p\n", ImageHandle));
1681 DEBUG ((DEBUG_GCD, " DeviceHandle = %p\n", DeviceHandle));
1682
1683 return CoreAllocateSpace (
1684 GCD_ALLOCATE_IO_OPERATION,
1685 GcdAllocateType,
1686 (EFI_GCD_MEMORY_TYPE) 0,
1687 GcdIoType,
1688 Alignment,
1689 Length,
1690 BaseAddress,
1691 ImageHandle,
1692 DeviceHandle
1693 );
1694 }
1695
1696
1697 /**
1698 Frees nonexistent I/O, reserved I/O, or I/O resources from the global coherency
1699 domain of the processor.
1700
1701 @param BaseAddress Base address of the segment.
1702 @param Length Length of the segment.
1703
1704 @retval EFI_SUCCESS Space successfully freed.
1705
1706 **/
1707 EFI_STATUS
1708 EFIAPI
1709 CoreFreeIoSpace (
1710 IN EFI_PHYSICAL_ADDRESS BaseAddress,
1711 IN UINT64 Length
1712 )
1713 {
1714 DEBUG ((DEBUG_GCD, "GCD:FreeIoSpace(Base=%016lx,Length=%016lx)\n", BaseAddress, Length));
1715
1716 return CoreConvertSpace (GCD_FREE_IO_OPERATION, (EFI_GCD_MEMORY_TYPE) 0, (EFI_GCD_IO_TYPE) 0, BaseAddress, Length, 0, 0);
1717 }
1718
1719
1720 /**
1721 Removes reserved I/O or I/O resources from the global coherency domain of the
1722 processor.
1723
1724 @param BaseAddress Base address of the segment.
1725 @param Length Length of the segment.
1726
1727 @retval EFI_SUCCESS Successfully removed a segment of IO space.
1728
1729 **/
1730 EFI_STATUS
1731 EFIAPI
1732 CoreRemoveIoSpace (
1733 IN EFI_PHYSICAL_ADDRESS BaseAddress,
1734 IN UINT64 Length
1735 )
1736 {
1737 DEBUG ((DEBUG_GCD, "GCD:RemoveIoSpace(Base=%016lx,Length=%016lx)\n", BaseAddress, Length));
1738
1739 return CoreConvertSpace (GCD_REMOVE_IO_OPERATION, (EFI_GCD_MEMORY_TYPE) 0, (EFI_GCD_IO_TYPE) 0, BaseAddress, Length, 0, 0);
1740 }
1741
1742
1743 /**
1744 Build a IO descriptor according to an entry.
1745
1746 @param Descriptor The descriptor to be built
1747 @param Entry According to this entry
1748
1749 **/
1750 VOID
1751 BuildIoDescriptor (
1752 IN EFI_GCD_IO_SPACE_DESCRIPTOR *Descriptor,
1753 IN EFI_GCD_MAP_ENTRY *Entry
1754 )
1755 {
1756 Descriptor->BaseAddress = Entry->BaseAddress;
1757 Descriptor->Length = Entry->EndAddress - Entry->BaseAddress + 1;
1758 Descriptor->GcdIoType = Entry->GcdIoType;
1759 Descriptor->ImageHandle = Entry->ImageHandle;
1760 Descriptor->DeviceHandle = Entry->DeviceHandle;
1761 }
1762
1763
1764 /**
1765 Retrieves the descriptor for an I/O region containing a specified address.
1766
1767 @param BaseAddress Specified start address
1768 @param Descriptor Specified length
1769
1770 @retval EFI_INVALID_PARAMETER Descriptor is NULL.
1771 @retval EFI_SUCCESS Successfully get the IO space descriptor.
1772
1773 **/
1774 EFI_STATUS
1775 EFIAPI
1776 CoreGetIoSpaceDescriptor (
1777 IN EFI_PHYSICAL_ADDRESS BaseAddress,
1778 OUT EFI_GCD_IO_SPACE_DESCRIPTOR *Descriptor
1779 )
1780 {
1781 EFI_STATUS Status;
1782 LIST_ENTRY *StartLink;
1783 LIST_ENTRY *EndLink;
1784 EFI_GCD_MAP_ENTRY *Entry;
1785
1786 //
1787 // Make sure parameters are valid
1788 //
1789 if (Descriptor == NULL) {
1790 return EFI_INVALID_PARAMETER;
1791 }
1792
1793 CoreAcquireGcdIoLock ();
1794
1795 //
1796 // Search for the list of descriptors that contain BaseAddress
1797 //
1798 Status = CoreSearchGcdMapEntry (BaseAddress, 1, &StartLink, &EndLink, &mGcdIoSpaceMap);
1799 if (EFI_ERROR (Status)) {
1800 Status = EFI_NOT_FOUND;
1801 } else {
1802 ASSERT (StartLink != NULL && EndLink != NULL);
1803 //
1804 // Copy the contents of the found descriptor into Descriptor
1805 //
1806 Entry = CR (StartLink, EFI_GCD_MAP_ENTRY, Link, EFI_GCD_MAP_SIGNATURE);
1807 BuildIoDescriptor (Descriptor, Entry);
1808 }
1809
1810 CoreReleaseGcdIoLock ();
1811
1812 return Status;
1813 }
1814
1815
1816 /**
1817 Returns a map of the I/O resources in the global coherency domain of the processor.
1818
1819 @param NumberOfDescriptors Number of descriptors.
1820 @param IoSpaceMap Descriptor array
1821
1822 @retval EFI_INVALID_PARAMETER Invalid parameter
1823 @retval EFI_OUT_OF_RESOURCES No enough buffer to allocate
1824 @retval EFI_SUCCESS Successfully get IO space map.
1825
1826 **/
1827 EFI_STATUS
1828 EFIAPI
1829 CoreGetIoSpaceMap (
1830 OUT UINTN *NumberOfDescriptors,
1831 OUT EFI_GCD_IO_SPACE_DESCRIPTOR **IoSpaceMap
1832 )
1833 {
1834 EFI_STATUS Status;
1835 LIST_ENTRY *Link;
1836 EFI_GCD_MAP_ENTRY *Entry;
1837 EFI_GCD_IO_SPACE_DESCRIPTOR *Descriptor;
1838
1839 //
1840 // Make sure parameters are valid
1841 //
1842 if (NumberOfDescriptors == NULL) {
1843 return EFI_INVALID_PARAMETER;
1844 }
1845 if (IoSpaceMap == NULL) {
1846 return EFI_INVALID_PARAMETER;
1847 }
1848
1849 CoreAcquireGcdIoLock ();
1850
1851 //
1852 // Count the number of descriptors
1853 //
1854 *NumberOfDescriptors = CoreCountGcdMapEntry (&mGcdIoSpaceMap);
1855
1856 //
1857 // Allocate the IoSpaceMap
1858 //
1859 *IoSpaceMap = AllocatePool (*NumberOfDescriptors * sizeof (EFI_GCD_IO_SPACE_DESCRIPTOR));
1860 if (*IoSpaceMap == NULL) {
1861 Status = EFI_OUT_OF_RESOURCES;
1862 goto Done;
1863 }
1864
1865 //
1866 // Fill in the IoSpaceMap
1867 //
1868 Descriptor = *IoSpaceMap;
1869 Link = mGcdIoSpaceMap.ForwardLink;
1870 while (Link != &mGcdIoSpaceMap) {
1871 Entry = CR (Link, EFI_GCD_MAP_ENTRY, Link, EFI_GCD_MAP_SIGNATURE);
1872 BuildIoDescriptor (Descriptor, Entry);
1873 Descriptor++;
1874 Link = Link->ForwardLink;
1875 }
1876 Status = EFI_SUCCESS;
1877
1878 Done:
1879 CoreReleaseGcdIoLock ();
1880 return Status;
1881 }
1882
1883
1884 /**
1885 Converts a Resource Descriptor HOB attributes mask to an EFI Memory Descriptor
1886 capabilities mask
1887
1888 @param GcdMemoryType Type of resource in the GCD memory map.
1889 @param Attributes The attribute mask in the Resource Descriptor
1890 HOB.
1891
1892 @return The capabilities mask for an EFI Memory Descriptor.
1893
1894 **/
1895 UINT64
1896 CoreConvertResourceDescriptorHobAttributesToCapabilities (
1897 EFI_GCD_MEMORY_TYPE GcdMemoryType,
1898 UINT64 Attributes
1899 )
1900 {
1901 UINT64 Capabilities;
1902 GCD_ATTRIBUTE_CONVERSION_ENTRY *Conversion;
1903
1904 //
1905 // Convert the Resource HOB Attributes to an EFI Memory Capabilities mask
1906 //
1907 for (Capabilities = 0, Conversion = mAttributeConversionTable; Conversion->Attribute != 0; Conversion++) {
1908 if (Conversion->Memory || (GcdMemoryType != EfiGcdMemoryTypeSystemMemory)) {
1909 if (Attributes & Conversion->Attribute) {
1910 Capabilities |= Conversion->Capability;
1911 }
1912 }
1913 }
1914
1915 return Capabilities;
1916 }
1917
1918
1919 /**
1920 External function. Initializes memory services based on the memory
1921 descriptor HOBs. This function is responsible for priming the memory
1922 map, so memory allocations and resource allocations can be made.
1923 The first part of this function can not depend on any memory services
1924 until at least one memory descriptor is provided to the memory services.
1925
1926 @param HobStart The start address of the HOB.
1927 @param MemoryBaseAddress Start address of memory region found to init DXE
1928 core.
1929 @param MemoryLength Length of memory region found to init DXE core.
1930
1931 @retval EFI_SUCCESS Memory services successfully initialized.
1932
1933 **/
1934 EFI_STATUS
1935 CoreInitializeMemoryServices (
1936 IN VOID **HobStart,
1937 OUT EFI_PHYSICAL_ADDRESS *MemoryBaseAddress,
1938 OUT UINT64 *MemoryLength
1939 )
1940 {
1941 EFI_PEI_HOB_POINTERS Hob;
1942 EFI_MEMORY_TYPE_INFORMATION *EfiMemoryTypeInformation;
1943 UINTN DataSize;
1944 BOOLEAN Found;
1945 EFI_HOB_HANDOFF_INFO_TABLE *PhitHob;
1946 EFI_HOB_RESOURCE_DESCRIPTOR *ResourceHob;
1947 EFI_HOB_RESOURCE_DESCRIPTOR *PhitResourceHob;
1948 EFI_PHYSICAL_ADDRESS BaseAddress;
1949 UINT64 Length;
1950 UINT64 Attributes;
1951 UINT64 Capabilities;
1952 EFI_PHYSICAL_ADDRESS MaxMemoryBaseAddress;
1953 UINT64 MaxMemoryLength;
1954 UINT64 MaxMemoryAttributes;
1955 EFI_PHYSICAL_ADDRESS TestedMemoryBaseAddress;
1956 UINT64 TestedMemoryLength;
1957 EFI_PHYSICAL_ADDRESS HighAddress;
1958 EFI_HOB_GUID_TYPE *GuidHob;
1959 UINT32 ReservedCodePageNumber;
1960
1961 //
1962 // Point at the first HOB. This must be the PHIT HOB.
1963 //
1964 Hob.Raw = *HobStart;
1965 ASSERT (GET_HOB_TYPE (Hob) == EFI_HOB_TYPE_HANDOFF);
1966
1967 //
1968 // Initialize the spin locks and maps in the memory services.
1969 // Also fill in the memory services into the EFI Boot Services Table
1970 //
1971 CoreInitializePool ();
1972
1973 //
1974 // Initialize Local Variables
1975 //
1976 PhitResourceHob = NULL;
1977 ResourceHob = NULL;
1978 BaseAddress = 0;
1979 Length = 0;
1980 Attributes = 0;
1981 MaxMemoryBaseAddress = 0;
1982 MaxMemoryLength = 0;
1983 MaxMemoryAttributes = 0;
1984
1985 //
1986 // Cache the PHIT HOB for later use
1987 //
1988 PhitHob = Hob.HandoffInformationTable;
1989
1990 if (PcdGet64(PcdLoadModuleAtFixAddressEnable) != 0) {
1991 ReservedCodePageNumber = PcdGet32(PcdLoadFixAddressRuntimeCodePageNumber);
1992 ReservedCodePageNumber += PcdGet32(PcdLoadFixAddressBootTimeCodePageNumber);
1993
1994 //
1995 // cache the Top address for loading modules at Fixed Address
1996 //
1997 gLoadModuleAtFixAddressConfigurationTable.DxeCodeTopAddress = PhitHob->EfiMemoryTop
1998 + EFI_PAGES_TO_SIZE(ReservedCodePageNumber);
1999 }
2000 //
2001 // See if a Memory Type Information HOB is available
2002 //
2003 GuidHob = GetFirstGuidHob (&gEfiMemoryTypeInformationGuid);
2004 if (GuidHob != NULL) {
2005 EfiMemoryTypeInformation = GET_GUID_HOB_DATA (GuidHob);
2006 DataSize = GET_GUID_HOB_DATA_SIZE (GuidHob);
2007 if (EfiMemoryTypeInformation != NULL && DataSize > 0 && DataSize <= (EfiMaxMemoryType + 1) * sizeof (EFI_MEMORY_TYPE_INFORMATION)) {
2008 CopyMem (&gMemoryTypeInformation, EfiMemoryTypeInformation, DataSize);
2009 }
2010 }
2011
2012 //
2013 // Find the Resource Descriptor HOB that contains PHIT range EfiFreeMemoryBottom..EfiFreeMemoryTop
2014 //
2015 Length = 0;
2016 Found = FALSE;
2017 for (Hob.Raw = *HobStart; !END_OF_HOB_LIST(Hob); Hob.Raw = GET_NEXT_HOB(Hob)) {
2018 //
2019 // Skip all HOBs except Resource Descriptor HOBs
2020 //
2021 if (GET_HOB_TYPE (Hob) != EFI_HOB_TYPE_RESOURCE_DESCRIPTOR) {
2022 continue;
2023 }
2024
2025 //
2026 // Skip Resource Descriptor HOBs that do not describe tested system memory
2027 //
2028 ResourceHob = Hob.ResourceDescriptor;
2029 if (ResourceHob->ResourceType != EFI_RESOURCE_SYSTEM_MEMORY) {
2030 continue;
2031 }
2032 if ((ResourceHob->ResourceAttribute & MEMORY_ATTRIBUTE_MASK) != TESTED_MEMORY_ATTRIBUTES) {
2033 continue;
2034 }
2035
2036 //
2037 // Skip Resource Descriptor HOBs that do not contain the PHIT range EfiFreeMemoryBottom..EfiFreeMemoryTop
2038 //
2039 if (PhitHob->EfiFreeMemoryBottom < ResourceHob->PhysicalStart) {
2040 continue;
2041 }
2042 if (PhitHob->EfiFreeMemoryTop > (ResourceHob->PhysicalStart + ResourceHob->ResourceLength)) {
2043 continue;
2044 }
2045
2046 //
2047 // Cache the resource descriptor HOB for the memory region described by the PHIT HOB
2048 //
2049 PhitResourceHob = ResourceHob;
2050 Found = TRUE;
2051
2052 //
2053 // Compute range between PHIT EfiFreeMemoryTop and the end of the Resource Descriptor HOB
2054 //
2055 Attributes = PhitResourceHob->ResourceAttribute;
2056 BaseAddress = PageAlignAddress (PhitHob->EfiMemoryTop);
2057 Length = PageAlignLength (ResourceHob->PhysicalStart + ResourceHob->ResourceLength - BaseAddress);
2058 if (Length < MINIMUM_INITIAL_MEMORY_SIZE) {
2059 //
2060 // If that range is not large enough to intialize the DXE Core, then
2061 // Compute range between PHIT EfiFreeMemoryBottom and PHIT EfiFreeMemoryTop
2062 //
2063 BaseAddress = PageAlignAddress (PhitHob->EfiFreeMemoryBottom);
2064 Length = PageAlignLength (PhitHob->EfiFreeMemoryTop - BaseAddress);
2065 if (Length < MINIMUM_INITIAL_MEMORY_SIZE) {
2066 //
2067 // If that range is not large enough to intialize the DXE Core, then
2068 // Compute range between the start of the Resource Descriptor HOB and the start of the HOB List
2069 //
2070 BaseAddress = PageAlignAddress (ResourceHob->PhysicalStart);
2071 Length = PageAlignLength ((UINT64)((UINTN)*HobStart - BaseAddress));
2072 }
2073 }
2074 break;
2075 }
2076
2077 //
2078 // Assert if a resource descriptor HOB for the memory region described by the PHIT was not found
2079 //
2080 ASSERT (Found);
2081
2082 //
2083 // Search all the resource descriptor HOBs from the highest possible addresses down for a memory
2084 // region that is big enough to initialize the DXE core. Always skip the PHIT Resource HOB.
2085 // The max address must be within the physically addressible range for the processor.
2086 //
2087 HighAddress = MAX_ADDRESS;
2088 for (Hob.Raw = *HobStart; !END_OF_HOB_LIST(Hob); Hob.Raw = GET_NEXT_HOB(Hob)) {
2089 //
2090 // Skip the Resource Descriptor HOB that contains the PHIT
2091 //
2092 if (Hob.ResourceDescriptor == PhitResourceHob) {
2093 continue;
2094 }
2095 //
2096 // Skip all HOBs except Resource Descriptor HOBs
2097 //
2098 if (GET_HOB_TYPE (Hob) != EFI_HOB_TYPE_RESOURCE_DESCRIPTOR) {
2099 continue;
2100 }
2101
2102 //
2103 // Skip Resource Descriptor HOBs that do not describe tested system memory below MAX_ADDRESS
2104 //
2105 ResourceHob = Hob.ResourceDescriptor;
2106 if (ResourceHob->ResourceType != EFI_RESOURCE_SYSTEM_MEMORY) {
2107 continue;
2108 }
2109 if ((ResourceHob->ResourceAttribute & MEMORY_ATTRIBUTE_MASK) != TESTED_MEMORY_ATTRIBUTES) {
2110 continue;
2111 }
2112 if ((ResourceHob->PhysicalStart + ResourceHob->ResourceLength) > (EFI_PHYSICAL_ADDRESS)MAX_ADDRESS) {
2113 continue;
2114 }
2115
2116 //
2117 // Skip Resource Descriptor HOBs that are below a previously found Resource Descriptor HOB
2118 //
2119 if (HighAddress != (EFI_PHYSICAL_ADDRESS)MAX_ADDRESS && ResourceHob->PhysicalStart <= HighAddress) {
2120 continue;
2121 }
2122
2123 //
2124 // Skip Resource Descriptor HOBs that are not large enough to initilize the DXE Core
2125 //
2126 TestedMemoryBaseAddress = PageAlignAddress (ResourceHob->PhysicalStart);
2127 TestedMemoryLength = PageAlignLength (ResourceHob->PhysicalStart + ResourceHob->ResourceLength - TestedMemoryBaseAddress);
2128 if (TestedMemoryLength < MINIMUM_INITIAL_MEMORY_SIZE) {
2129 continue;
2130 }
2131
2132 //
2133 // Save the Resource Descriptor HOB context that is large enough to initilize the DXE Core
2134 //
2135 MaxMemoryBaseAddress = TestedMemoryBaseAddress;
2136 MaxMemoryLength = TestedMemoryLength;
2137 MaxMemoryAttributes = ResourceHob->ResourceAttribute;
2138 HighAddress = ResourceHob->PhysicalStart;
2139 }
2140
2141 //
2142 // If Length is not large enough to initialize the DXE Core or a Resource
2143 // Descriptor HOB was found above the PHIT HOB that is large enough to initialize
2144 // the DXE Core, then use the range described by the Resource Descriptor
2145 // HOB that was found above the PHIT HOB.
2146 //
2147 if ((Length < MINIMUM_INITIAL_MEMORY_SIZE) ||
2148 (MaxMemoryBaseAddress > BaseAddress && MaxMemoryLength >= MINIMUM_INITIAL_MEMORY_SIZE)) {
2149 BaseAddress = MaxMemoryBaseAddress;
2150 Length = MaxMemoryLength;
2151 Attributes = MaxMemoryAttributes;
2152 }
2153
2154 //
2155 // If no memory regions are found that are big enough to initialize the DXE core, then ASSERT().
2156 //
2157 ASSERT (Length >= MINIMUM_INITIAL_MEMORY_SIZE);
2158
2159 //
2160 // Convert the Resource HOB Attributes to an EFI Memory Capabilities mask
2161 //
2162 Capabilities = CoreConvertResourceDescriptorHobAttributesToCapabilities (EfiGcdMemoryTypeSystemMemory, Attributes);
2163
2164 //
2165 // Declare the very first memory region, so the EFI Memory Services are available.
2166 //
2167 CoreAddMemoryDescriptor (
2168 EfiConventionalMemory,
2169 BaseAddress,
2170 RShiftU64 (Length, EFI_PAGE_SHIFT),
2171 Capabilities
2172 );
2173
2174 *MemoryBaseAddress = BaseAddress;
2175 *MemoryLength = Length;
2176
2177 return EFI_SUCCESS;
2178 }
2179
2180
2181 /**
2182 External function. Initializes the GCD and memory services based on the memory
2183 descriptor HOBs. This function is responsible for priming the GCD map and the
2184 memory map, so memory allocations and resource allocations can be made. The
2185 HobStart will be relocated to a pool buffer.
2186
2187 @param HobStart The start address of the HOB
2188 @param MemoryBaseAddress Start address of memory region found to init DXE
2189 core.
2190 @param MemoryLength Length of memory region found to init DXE core.
2191
2192 @retval EFI_SUCCESS GCD services successfully initialized.
2193
2194 **/
2195 EFI_STATUS
2196 CoreInitializeGcdServices (
2197 IN OUT VOID **HobStart,
2198 IN EFI_PHYSICAL_ADDRESS MemoryBaseAddress,
2199 IN UINT64 MemoryLength
2200 )
2201 {
2202 EFI_PEI_HOB_POINTERS Hob;
2203 VOID *NewHobList;
2204 EFI_HOB_HANDOFF_INFO_TABLE *PhitHob;
2205 UINT8 SizeOfMemorySpace;
2206 UINT8 SizeOfIoSpace;
2207 EFI_HOB_RESOURCE_DESCRIPTOR *ResourceHob;
2208 EFI_PHYSICAL_ADDRESS BaseAddress;
2209 UINT64 Length;
2210 EFI_STATUS Status;
2211 EFI_GCD_MAP_ENTRY *Entry;
2212 EFI_GCD_MEMORY_TYPE GcdMemoryType;
2213 EFI_GCD_IO_TYPE GcdIoType;
2214 EFI_GCD_MEMORY_SPACE_DESCRIPTOR Descriptor;
2215 EFI_HOB_MEMORY_ALLOCATION *MemoryHob;
2216 EFI_HOB_FIRMWARE_VOLUME *FirmwareVolumeHob;
2217 UINTN NumberOfDescriptors;
2218 EFI_GCD_MEMORY_SPACE_DESCRIPTOR *MemorySpaceMap;
2219 UINTN Index;
2220 UINT64 Capabilities;
2221 EFI_HOB_CPU * CpuHob;
2222
2223 //
2224 // Cache the PHIT HOB for later use
2225 //
2226 PhitHob = (EFI_HOB_HANDOFF_INFO_TABLE *)(*HobStart);
2227
2228 //
2229 // Get the number of address lines in the I/O and Memory space for the CPU
2230 //
2231 CpuHob = GetFirstHob (EFI_HOB_TYPE_CPU);
2232 ASSERT (CpuHob != NULL);
2233 SizeOfMemorySpace = CpuHob->SizeOfMemorySpace;
2234 SizeOfIoSpace = CpuHob->SizeOfIoSpace;
2235
2236 //
2237 // Initialize the GCD Memory Space Map
2238 //
2239 Entry = AllocateCopyPool (sizeof (EFI_GCD_MAP_ENTRY), &mGcdMemorySpaceMapEntryTemplate);
2240 ASSERT (Entry != NULL);
2241
2242 Entry->EndAddress = LShiftU64 (1, SizeOfMemorySpace) - 1;
2243
2244 InsertHeadList (&mGcdMemorySpaceMap, &Entry->Link);
2245
2246 CoreDumpGcdMemorySpaceMap (TRUE);
2247
2248 //
2249 // Initialize the GCD I/O Space Map
2250 //
2251 Entry = AllocateCopyPool (sizeof (EFI_GCD_MAP_ENTRY), &mGcdIoSpaceMapEntryTemplate);
2252 ASSERT (Entry != NULL);
2253
2254 Entry->EndAddress = LShiftU64 (1, SizeOfIoSpace) - 1;
2255
2256 InsertHeadList (&mGcdIoSpaceMap, &Entry->Link);
2257
2258 CoreDumpGcdIoSpaceMap (TRUE);
2259
2260 //
2261 // Walk the HOB list and add all resource descriptors to the GCD
2262 //
2263 for (Hob.Raw = *HobStart; !END_OF_HOB_LIST(Hob); Hob.Raw = GET_NEXT_HOB(Hob)) {
2264
2265 GcdMemoryType = EfiGcdMemoryTypeNonExistent;
2266 GcdIoType = EfiGcdIoTypeNonExistent;
2267
2268 if (GET_HOB_TYPE (Hob) == EFI_HOB_TYPE_RESOURCE_DESCRIPTOR) {
2269
2270 ResourceHob = Hob.ResourceDescriptor;
2271
2272 switch (ResourceHob->ResourceType) {
2273 case EFI_RESOURCE_SYSTEM_MEMORY:
2274 if ((ResourceHob->ResourceAttribute & MEMORY_ATTRIBUTE_MASK) == TESTED_MEMORY_ATTRIBUTES) {
2275 GcdMemoryType = EfiGcdMemoryTypeSystemMemory;
2276 }
2277 if ((ResourceHob->ResourceAttribute & MEMORY_ATTRIBUTE_MASK) == INITIALIZED_MEMORY_ATTRIBUTES) {
2278 GcdMemoryType = EfiGcdMemoryTypeReserved;
2279 }
2280 if ((ResourceHob->ResourceAttribute & MEMORY_ATTRIBUTE_MASK) == PRESENT_MEMORY_ATTRIBUTES) {
2281 GcdMemoryType = EfiGcdMemoryTypeReserved;
2282 }
2283 break;
2284 case EFI_RESOURCE_MEMORY_MAPPED_IO:
2285 case EFI_RESOURCE_FIRMWARE_DEVICE:
2286 GcdMemoryType = EfiGcdMemoryTypeMemoryMappedIo;
2287 break;
2288 case EFI_RESOURCE_MEMORY_MAPPED_IO_PORT:
2289 case EFI_RESOURCE_MEMORY_RESERVED:
2290 GcdMemoryType = EfiGcdMemoryTypeReserved;
2291 break;
2292 case EFI_RESOURCE_IO:
2293 GcdIoType = EfiGcdIoTypeIo;
2294 break;
2295 case EFI_RESOURCE_IO_RESERVED:
2296 GcdIoType = EfiGcdIoTypeReserved;
2297 break;
2298 }
2299
2300 if (GcdMemoryType != EfiGcdMemoryTypeNonExistent) {
2301 //
2302 // Validate the Resource HOB Attributes
2303 //
2304 CoreValidateResourceDescriptorHobAttributes (ResourceHob->ResourceAttribute);
2305
2306 //
2307 // Convert the Resource HOB Attributes to an EFI Memory Capabilities mask
2308 //
2309 Capabilities = CoreConvertResourceDescriptorHobAttributesToCapabilities (
2310 GcdMemoryType,
2311 ResourceHob->ResourceAttribute
2312 );
2313
2314 Status = CoreInternalAddMemorySpace (
2315 GcdMemoryType,
2316 ResourceHob->PhysicalStart,
2317 ResourceHob->ResourceLength,
2318 Capabilities
2319 );
2320 }
2321
2322 if (GcdIoType != EfiGcdIoTypeNonExistent) {
2323 Status = CoreAddIoSpace (
2324 GcdIoType,
2325 ResourceHob->PhysicalStart,
2326 ResourceHob->ResourceLength
2327 );
2328 }
2329 }
2330 }
2331
2332 //
2333 // Allocate first memory region from the GCD by the DXE core
2334 //
2335 Status = CoreAllocateMemorySpace (
2336 EfiGcdAllocateAddress,
2337 EfiGcdMemoryTypeSystemMemory,
2338 0,
2339 MemoryLength,
2340 &MemoryBaseAddress,
2341 gDxeCoreImageHandle,
2342 NULL
2343 );
2344
2345 //
2346 // Walk the HOB list and allocate all memory space that is consumed by memory allocation HOBs,
2347 // and Firmware Volume HOBs. Also update the EFI Memory Map with the memory allocation HOBs.
2348 //
2349 for (Hob.Raw = *HobStart; !END_OF_HOB_LIST(Hob); Hob.Raw = GET_NEXT_HOB(Hob)) {
2350 if (GET_HOB_TYPE (Hob) == EFI_HOB_TYPE_MEMORY_ALLOCATION) {
2351 MemoryHob = Hob.MemoryAllocation;
2352 BaseAddress = MemoryHob->AllocDescriptor.MemoryBaseAddress;
2353 Status = CoreGetMemorySpaceDescriptor (BaseAddress, &Descriptor);
2354 if (!EFI_ERROR (Status)) {
2355 Status = CoreAllocateMemorySpace (
2356 EfiGcdAllocateAddress,
2357 Descriptor.GcdMemoryType,
2358 0,
2359 MemoryHob->AllocDescriptor.MemoryLength,
2360 &BaseAddress,
2361 gDxeCoreImageHandle,
2362 NULL
2363 );
2364 if (!EFI_ERROR (Status) && Descriptor.GcdMemoryType == EfiGcdMemoryTypeSystemMemory) {
2365 CoreAddMemoryDescriptor (
2366 MemoryHob->AllocDescriptor.MemoryType,
2367 MemoryHob->AllocDescriptor.MemoryBaseAddress,
2368 RShiftU64 (MemoryHob->AllocDescriptor.MemoryLength, EFI_PAGE_SHIFT),
2369 Descriptor.Capabilities & (~EFI_MEMORY_RUNTIME)
2370 );
2371 }
2372 }
2373 }
2374
2375 if (GET_HOB_TYPE (Hob) == EFI_HOB_TYPE_FV) {
2376 FirmwareVolumeHob = Hob.FirmwareVolume;
2377 BaseAddress = FirmwareVolumeHob->BaseAddress;
2378 Status = CoreAllocateMemorySpace (
2379 EfiGcdAllocateAddress,
2380 EfiGcdMemoryTypeMemoryMappedIo,
2381 0,
2382 FirmwareVolumeHob->Length,
2383 &BaseAddress,
2384 gDxeCoreImageHandle,
2385 NULL
2386 );
2387 }
2388 }
2389
2390 //
2391 // Relocate HOB List to an allocated pool buffer.
2392 //
2393 NewHobList = AllocateCopyPool (
2394 (UINTN)PhitHob->EfiFreeMemoryBottom - (UINTN)(*HobStart),
2395 *HobStart
2396 );
2397 ASSERT (NewHobList != NULL);
2398
2399 *HobStart = NewHobList;
2400 gHobList = NewHobList;
2401
2402 //
2403 // Add and allocate the remaining unallocated system memory to the memory services.
2404 //
2405 Status = CoreGetMemorySpaceMap (&NumberOfDescriptors, &MemorySpaceMap);
2406 ASSERT (Status == EFI_SUCCESS);
2407
2408 for (Index = 0; Index < NumberOfDescriptors; Index++) {
2409 if (MemorySpaceMap[Index].GcdMemoryType == EfiGcdMemoryTypeSystemMemory) {
2410 if (MemorySpaceMap[Index].ImageHandle == NULL) {
2411 BaseAddress = PageAlignAddress (MemorySpaceMap[Index].BaseAddress);
2412 Length = PageAlignLength (MemorySpaceMap[Index].BaseAddress + MemorySpaceMap[Index].Length - BaseAddress);
2413 if (Length == 0 || MemorySpaceMap[Index].BaseAddress + MemorySpaceMap[Index].Length < BaseAddress) {
2414 continue;
2415 }
2416 CoreAddMemoryDescriptor (
2417 EfiConventionalMemory,
2418 BaseAddress,
2419 RShiftU64 (Length, EFI_PAGE_SHIFT),
2420 MemorySpaceMap[Index].Capabilities & (~EFI_MEMORY_RUNTIME)
2421 );
2422 Status = CoreAllocateMemorySpace (
2423 EfiGcdAllocateAddress,
2424 EfiGcdMemoryTypeSystemMemory,
2425 0,
2426 Length,
2427 &BaseAddress,
2428 gDxeCoreImageHandle,
2429 NULL
2430 );
2431 }
2432 }
2433 }
2434 CoreFreePool (MemorySpaceMap);
2435
2436 return EFI_SUCCESS;
2437 }