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