]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Core/Dxe/Gcd/Gcd.c
MdeModulePkg: fix mixed dos and linux EOL format issue
[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 - 2014, 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 (Status == EFI_SUCCESS && MemorySpaceMap != NULL);
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 (Status == EFI_SUCCESS && IoSpaceMap != NULL);
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 @retval EFI_NOT_AVAILABLE_YET The attributes cannot be set because CPU architectural protocol
693 is not available yet.
694 **/
695 EFI_STATUS
696 CoreConvertSpace (
697 IN UINTN Operation,
698 IN EFI_GCD_MEMORY_TYPE GcdMemoryType,
699 IN EFI_GCD_IO_TYPE GcdIoType,
700 IN EFI_PHYSICAL_ADDRESS BaseAddress,
701 IN UINT64 Length,
702 IN UINT64 Capabilities,
703 IN UINT64 Attributes
704 )
705 {
706 EFI_STATUS Status;
707 LIST_ENTRY *Map;
708 LIST_ENTRY *Link;
709 EFI_GCD_MAP_ENTRY *Entry;
710 EFI_GCD_MAP_ENTRY *TopEntry;
711 EFI_GCD_MAP_ENTRY *BottomEntry;
712 LIST_ENTRY *StartLink;
713 LIST_ENTRY *EndLink;
714 UINT64 CpuArchAttributes;
715
716 if (Length == 0) {
717 DEBUG ((DEBUG_GCD, " Status = %r\n", EFI_INVALID_PARAMETER));
718 return EFI_INVALID_PARAMETER;
719 }
720
721 Map = NULL;
722 if ((Operation & GCD_MEMORY_SPACE_OPERATION) != 0) {
723 CoreAcquireGcdMemoryLock ();
724 Map = &mGcdMemorySpaceMap;
725 } else if ((Operation & GCD_IO_SPACE_OPERATION) != 0) {
726 CoreAcquireGcdIoLock ();
727 Map = &mGcdIoSpaceMap;
728 } else {
729 ASSERT (FALSE);
730 }
731
732 //
733 // Search for the list of descriptors that cover the range BaseAddress to BaseAddress+Length
734 //
735 Status = CoreSearchGcdMapEntry (BaseAddress, Length, &StartLink, &EndLink, Map);
736 if (EFI_ERROR (Status)) {
737 Status = EFI_UNSUPPORTED;
738
739 goto Done;
740 }
741 ASSERT (StartLink != NULL && EndLink != NULL);
742
743 //
744 // Verify that the list of descriptors are unallocated non-existent memory.
745 //
746 Link = StartLink;
747 while (Link != EndLink->ForwardLink) {
748 Entry = CR (Link, EFI_GCD_MAP_ENTRY, Link, EFI_GCD_MAP_SIGNATURE);
749 switch (Operation) {
750 //
751 // Add operations
752 //
753 case GCD_ADD_MEMORY_OPERATION:
754 if (Entry->GcdMemoryType != EfiGcdMemoryTypeNonExistent ||
755 Entry->ImageHandle != NULL ) {
756 Status = EFI_ACCESS_DENIED;
757 goto Done;
758 }
759 break;
760 case GCD_ADD_IO_OPERATION:
761 if (Entry->GcdIoType != EfiGcdIoTypeNonExistent ||
762 Entry->ImageHandle != NULL ) {
763 Status = EFI_ACCESS_DENIED;
764 goto Done;
765 }
766 break;
767 //
768 // Free operations
769 //
770 case GCD_FREE_MEMORY_OPERATION:
771 case GCD_FREE_IO_OPERATION:
772 if (Entry->ImageHandle == NULL) {
773 Status = EFI_NOT_FOUND;
774 goto Done;
775 }
776 break;
777 //
778 // Remove operations
779 //
780 case GCD_REMOVE_MEMORY_OPERATION:
781 if (Entry->GcdMemoryType == EfiGcdMemoryTypeNonExistent) {
782 Status = EFI_NOT_FOUND;
783 goto Done;
784 }
785 if (Entry->ImageHandle != NULL) {
786 Status = EFI_ACCESS_DENIED;
787 goto Done;
788 }
789 break;
790 case GCD_REMOVE_IO_OPERATION:
791 if (Entry->GcdIoType == EfiGcdIoTypeNonExistent) {
792 Status = EFI_NOT_FOUND;
793 goto Done;
794 }
795 if (Entry->ImageHandle != NULL) {
796 Status = EFI_ACCESS_DENIED;
797 goto Done;
798 }
799 break;
800 //
801 // Set attributes operation
802 //
803 case GCD_SET_ATTRIBUTES_MEMORY_OPERATION:
804 if ((Attributes & EFI_MEMORY_RUNTIME) != 0) {
805 if ((BaseAddress & EFI_PAGE_MASK) != 0 || (Length & EFI_PAGE_MASK) != 0) {
806 Status = EFI_INVALID_PARAMETER;
807 goto Done;
808 }
809 }
810 if ((Entry->Capabilities & Attributes) != Attributes) {
811 Status = EFI_UNSUPPORTED;
812 goto Done;
813 }
814 break;
815 //
816 // Set capabilities operation
817 //
818 case GCD_SET_CAPABILITIES_MEMORY_OPERATION:
819 if ((BaseAddress & EFI_PAGE_MASK) != 0 || (Length & EFI_PAGE_MASK) != 0) {
820 Status = EFI_INVALID_PARAMETER;
821
822 goto Done;
823 }
824 //
825 // Current attributes must still be supported with new capabilities
826 //
827 if ((Capabilities & Entry->Attributes) != Entry->Attributes) {
828 Status = EFI_UNSUPPORTED;
829 goto Done;
830 }
831 break;
832 }
833 Link = Link->ForwardLink;
834 }
835
836 //
837 // Allocate work space to perform this operation
838 //
839 Status = CoreAllocateGcdMapEntry (&TopEntry, &BottomEntry);
840 if (EFI_ERROR (Status)) {
841 Status = EFI_OUT_OF_RESOURCES;
842 goto Done;
843 }
844 ASSERT (TopEntry != NULL && BottomEntry != NULL);
845
846 if (Operation == GCD_SET_ATTRIBUTES_MEMORY_OPERATION) {
847 //
848 // Call CPU Arch Protocol to attempt to set attributes on the range
849 //
850 CpuArchAttributes = ConverToCpuArchAttributes (Attributes);
851 if (CpuArchAttributes != INVALID_CPU_ARCH_ATTRIBUTES) {
852 if (gCpu == NULL) {
853 Status = EFI_NOT_AVAILABLE_YET;
854 } else {
855 Status = gCpu->SetMemoryAttributes (
856 gCpu,
857 BaseAddress,
858 Length,
859 CpuArchAttributes
860 );
861 }
862 if (EFI_ERROR (Status)) {
863 CoreFreePool (TopEntry);
864 CoreFreePool (BottomEntry);
865 goto Done;
866 }
867 }
868 }
869
870 //
871 // Convert/Insert the list of descriptors from StartLink to EndLink
872 //
873 Link = StartLink;
874 while (Link != EndLink->ForwardLink) {
875 Entry = CR (Link, EFI_GCD_MAP_ENTRY, Link, EFI_GCD_MAP_SIGNATURE);
876 CoreInsertGcdMapEntry (Link, Entry, BaseAddress, Length, TopEntry, BottomEntry);
877 switch (Operation) {
878 //
879 // Add operations
880 //
881 case GCD_ADD_MEMORY_OPERATION:
882 Entry->GcdMemoryType = GcdMemoryType;
883 if (GcdMemoryType == EfiGcdMemoryTypeMemoryMappedIo) {
884 Entry->Capabilities = Capabilities | EFI_MEMORY_RUNTIME | EFI_MEMORY_PORT_IO;
885 } else {
886 Entry->Capabilities = Capabilities | EFI_MEMORY_RUNTIME;
887 }
888 break;
889 case GCD_ADD_IO_OPERATION:
890 Entry->GcdIoType = GcdIoType;
891 break;
892 //
893 // Free operations
894 //
895 case GCD_FREE_MEMORY_OPERATION:
896 case GCD_FREE_IO_OPERATION:
897 Entry->ImageHandle = NULL;
898 Entry->DeviceHandle = NULL;
899 break;
900 //
901 // Remove operations
902 //
903 case GCD_REMOVE_MEMORY_OPERATION:
904 Entry->GcdMemoryType = EfiGcdMemoryTypeNonExistent;
905 Entry->Capabilities = 0;
906 break;
907 case GCD_REMOVE_IO_OPERATION:
908 Entry->GcdIoType = EfiGcdIoTypeNonExistent;
909 break;
910 //
911 // Set attributes operation
912 //
913 case GCD_SET_ATTRIBUTES_MEMORY_OPERATION:
914 Entry->Attributes = Attributes;
915 break;
916 //
917 // Set capabilities operation
918 //
919 case GCD_SET_CAPABILITIES_MEMORY_OPERATION:
920 Entry->Capabilities = Capabilities;
921 break;
922 }
923 Link = Link->ForwardLink;
924 }
925
926 //
927 // Cleanup
928 //
929 Status = CoreCleanupGcdMapEntry (TopEntry, BottomEntry, StartLink, EndLink, Map);
930
931 Done:
932 DEBUG ((DEBUG_GCD, " Status = %r\n", Status));
933
934 if ((Operation & GCD_MEMORY_SPACE_OPERATION) != 0) {
935 CoreReleaseGcdMemoryLock ();
936 CoreDumpGcdMemorySpaceMap (FALSE);
937 }
938 if ((Operation & GCD_IO_SPACE_OPERATION) != 0) {
939 CoreReleaseGcdIoLock ();
940 CoreDumpGcdIoSpaceMap (FALSE);
941 }
942
943 return Status;
944 }
945
946
947 /**
948 Check whether an entry could be used to allocate space.
949
950 @param Operation Allocate memory or IO
951 @param Entry The entry to be tested
952 @param GcdMemoryType The desired memory type
953 @param GcdIoType The desired IO type
954
955 @retval EFI_NOT_FOUND The memory type does not match or there's an
956 image handle on the entry.
957 @retval EFI_UNSUPPORTED The operation unsupported.
958 @retval EFI_SUCCESS It's ok for this entry to be used to allocate
959 space.
960
961 **/
962 EFI_STATUS
963 CoreAllocateSpaceCheckEntry (
964 IN UINTN Operation,
965 IN EFI_GCD_MAP_ENTRY *Entry,
966 IN EFI_GCD_MEMORY_TYPE GcdMemoryType,
967 IN EFI_GCD_IO_TYPE GcdIoType
968 )
969 {
970 if (Entry->ImageHandle != NULL) {
971 return EFI_NOT_FOUND;
972 }
973 switch (Operation) {
974 case GCD_ALLOCATE_MEMORY_OPERATION:
975 if (Entry->GcdMemoryType != GcdMemoryType) {
976 return EFI_NOT_FOUND;
977 }
978 break;
979 case GCD_ALLOCATE_IO_OPERATION:
980 if (Entry->GcdIoType != GcdIoType) {
981 return EFI_NOT_FOUND;
982 }
983 break;
984 default:
985 return EFI_UNSUPPORTED;
986 }
987 return EFI_SUCCESS;
988 }
989
990
991 /**
992 Allocate space on specified address and length.
993
994 @param Operation The type of operation (memory or IO)
995 @param GcdAllocateType The type of allocate operation
996 @param GcdMemoryType The desired memory type
997 @param GcdIoType The desired IO type
998 @param Alignment Align with 2^Alignment
999 @param Length Length to allocate
1000 @param BaseAddress Base address to allocate
1001 @param ImageHandle The image handle consume the allocated space.
1002 @param DeviceHandle The device handle consume the allocated space.
1003
1004 @retval EFI_INVALID_PARAMETER Invalid parameter.
1005 @retval EFI_NOT_FOUND No descriptor for the desired space exists.
1006 @retval EFI_SUCCESS Space successfully allocated.
1007
1008 **/
1009 EFI_STATUS
1010 CoreAllocateSpace (
1011 IN UINTN Operation,
1012 IN EFI_GCD_ALLOCATE_TYPE GcdAllocateType,
1013 IN EFI_GCD_MEMORY_TYPE GcdMemoryType,
1014 IN EFI_GCD_IO_TYPE GcdIoType,
1015 IN UINTN Alignment,
1016 IN UINT64 Length,
1017 IN OUT EFI_PHYSICAL_ADDRESS *BaseAddress,
1018 IN EFI_HANDLE ImageHandle,
1019 IN EFI_HANDLE DeviceHandle OPTIONAL
1020 )
1021 {
1022 EFI_STATUS Status;
1023 EFI_PHYSICAL_ADDRESS AlignmentMask;
1024 EFI_PHYSICAL_ADDRESS MaxAddress;
1025 LIST_ENTRY *Map;
1026 LIST_ENTRY *Link;
1027 LIST_ENTRY *SubLink;
1028 EFI_GCD_MAP_ENTRY *Entry;
1029 EFI_GCD_MAP_ENTRY *TopEntry;
1030 EFI_GCD_MAP_ENTRY *BottomEntry;
1031 LIST_ENTRY *StartLink;
1032 LIST_ENTRY *EndLink;
1033 BOOLEAN Found;
1034
1035 //
1036 // Make sure parameters are valid
1037 //
1038 if ((UINT32)GcdAllocateType >= EfiGcdMaxAllocateType) {
1039 DEBUG ((DEBUG_GCD, " Status = %r\n", EFI_INVALID_PARAMETER));
1040 return EFI_INVALID_PARAMETER;
1041 }
1042 if ((UINT32)GcdMemoryType >= EfiGcdMemoryTypeMaximum) {
1043 DEBUG ((DEBUG_GCD, " Status = %r\n", EFI_INVALID_PARAMETER));
1044 return EFI_INVALID_PARAMETER;
1045 }
1046 if ((UINT32)GcdIoType >= EfiGcdIoTypeMaximum) {
1047 DEBUG ((DEBUG_GCD, " Status = %r\n", EFI_INVALID_PARAMETER));
1048 return EFI_INVALID_PARAMETER;
1049 }
1050 if (BaseAddress == NULL) {
1051 DEBUG ((DEBUG_GCD, " Status = %r\n", EFI_INVALID_PARAMETER));
1052 return EFI_INVALID_PARAMETER;
1053 }
1054 if (ImageHandle == NULL) {
1055 DEBUG ((DEBUG_GCD, " Status = %r\n", EFI_INVALID_PARAMETER));
1056 return EFI_INVALID_PARAMETER;
1057 }
1058 if (Alignment >= 64) {
1059 DEBUG ((DEBUG_GCD, " Status = %r\n", EFI_NOT_FOUND));
1060 return EFI_NOT_FOUND;
1061 }
1062 if (Length == 0) {
1063 DEBUG ((DEBUG_GCD, " Status = %r\n", EFI_INVALID_PARAMETER));
1064 return EFI_INVALID_PARAMETER;
1065 }
1066
1067 Map = NULL;
1068 if ((Operation & GCD_MEMORY_SPACE_OPERATION) != 0) {
1069 CoreAcquireGcdMemoryLock ();
1070 Map = &mGcdMemorySpaceMap;
1071 } else if ((Operation & GCD_IO_SPACE_OPERATION) != 0) {
1072 CoreAcquireGcdIoLock ();
1073 Map = &mGcdIoSpaceMap;
1074 } else {
1075 ASSERT (FALSE);
1076 }
1077
1078 Found = FALSE;
1079 StartLink = NULL;
1080 EndLink = NULL;
1081 //
1082 // Compute alignment bit mask
1083 //
1084 AlignmentMask = LShiftU64 (1, Alignment) - 1;
1085
1086 if (GcdAllocateType == EfiGcdAllocateAddress) {
1087 //
1088 // Verify that the BaseAddress passed in is aligned correctly
1089 //
1090 if ((*BaseAddress & AlignmentMask) != 0) {
1091 Status = EFI_NOT_FOUND;
1092 goto Done;
1093 }
1094
1095 //
1096 // Search for the list of descriptors that cover the range BaseAddress to BaseAddress+Length
1097 //
1098 Status = CoreSearchGcdMapEntry (*BaseAddress, Length, &StartLink, &EndLink, Map);
1099 if (EFI_ERROR (Status)) {
1100 Status = EFI_NOT_FOUND;
1101 goto Done;
1102 }
1103 ASSERT (StartLink != NULL && EndLink != NULL);
1104
1105 //
1106 // Verify that the list of descriptors are unallocated memory matching GcdMemoryType.
1107 //
1108 Link = StartLink;
1109 while (Link != EndLink->ForwardLink) {
1110 Entry = CR (Link, EFI_GCD_MAP_ENTRY, Link, EFI_GCD_MAP_SIGNATURE);
1111 Link = Link->ForwardLink;
1112 Status = CoreAllocateSpaceCheckEntry (Operation, Entry, GcdMemoryType, GcdIoType);
1113 if (EFI_ERROR (Status)) {
1114 goto Done;
1115 }
1116 }
1117 Found = TRUE;
1118 } else {
1119
1120 Entry = CR (Map->BackLink, EFI_GCD_MAP_ENTRY, Link, EFI_GCD_MAP_SIGNATURE);
1121
1122 //
1123 // Compute the maximum address to use in the search algorithm
1124 //
1125 if (GcdAllocateType == EfiGcdAllocateMaxAddressSearchBottomUp ||
1126 GcdAllocateType == EfiGcdAllocateMaxAddressSearchTopDown ) {
1127 MaxAddress = *BaseAddress;
1128 } else {
1129 MaxAddress = Entry->EndAddress;
1130 }
1131
1132 //
1133 // Verify that the list of descriptors are unallocated memory matching GcdMemoryType.
1134 //
1135 if (GcdAllocateType == EfiGcdAllocateMaxAddressSearchTopDown ||
1136 GcdAllocateType == EfiGcdAllocateAnySearchTopDown ) {
1137 Link = Map->BackLink;
1138 } else {
1139 Link = Map->ForwardLink;
1140 }
1141 while (Link != Map) {
1142 Entry = CR (Link, EFI_GCD_MAP_ENTRY, Link, EFI_GCD_MAP_SIGNATURE);
1143
1144 if (GcdAllocateType == EfiGcdAllocateMaxAddressSearchTopDown ||
1145 GcdAllocateType == EfiGcdAllocateAnySearchTopDown ) {
1146 Link = Link->BackLink;
1147 } else {
1148 Link = Link->ForwardLink;
1149 }
1150
1151 Status = CoreAllocateSpaceCheckEntry (Operation, Entry, GcdMemoryType, GcdIoType);
1152 if (EFI_ERROR (Status)) {
1153 continue;
1154 }
1155
1156 if (GcdAllocateType == EfiGcdAllocateMaxAddressSearchTopDown ||
1157 GcdAllocateType == EfiGcdAllocateAnySearchTopDown) {
1158 if ((Entry->BaseAddress + Length) > MaxAddress) {
1159 continue;
1160 }
1161 if (Length > (Entry->EndAddress + 1)) {
1162 Status = EFI_NOT_FOUND;
1163 goto Done;
1164 }
1165 if (Entry->EndAddress > MaxAddress) {
1166 *BaseAddress = MaxAddress;
1167 } else {
1168 *BaseAddress = Entry->EndAddress;
1169 }
1170 *BaseAddress = (*BaseAddress + 1 - Length) & (~AlignmentMask);
1171 } else {
1172 *BaseAddress = (Entry->BaseAddress + AlignmentMask) & (~AlignmentMask);
1173 if ((*BaseAddress + Length - 1) > MaxAddress) {
1174 Status = EFI_NOT_FOUND;
1175 goto Done;
1176 }
1177 }
1178
1179 //
1180 // Search for the list of descriptors that cover the range BaseAddress to BaseAddress+Length
1181 //
1182 Status = CoreSearchGcdMapEntry (*BaseAddress, Length, &StartLink, &EndLink, Map);
1183 if (EFI_ERROR (Status)) {
1184 Status = EFI_NOT_FOUND;
1185 goto Done;
1186 }
1187 ASSERT (StartLink != NULL && EndLink != NULL);
1188
1189 Link = StartLink;
1190 //
1191 // Verify that the list of descriptors are unallocated memory matching GcdMemoryType.
1192 //
1193 Found = TRUE;
1194 SubLink = StartLink;
1195 while (SubLink != EndLink->ForwardLink) {
1196 Entry = CR (SubLink, EFI_GCD_MAP_ENTRY, Link, EFI_GCD_MAP_SIGNATURE);
1197 Status = CoreAllocateSpaceCheckEntry (Operation, Entry, GcdMemoryType, GcdIoType);
1198 if (EFI_ERROR (Status)) {
1199 Link = SubLink;
1200 Found = FALSE;
1201 break;
1202 }
1203 SubLink = SubLink->ForwardLink;
1204 }
1205 if (Found) {
1206 break;
1207 }
1208 }
1209 }
1210 if (!Found) {
1211 Status = EFI_NOT_FOUND;
1212 goto Done;
1213 }
1214
1215 //
1216 // Allocate work space to perform this operation
1217 //
1218 Status = CoreAllocateGcdMapEntry (&TopEntry, &BottomEntry);
1219 if (EFI_ERROR (Status)) {
1220 Status = EFI_OUT_OF_RESOURCES;
1221 goto Done;
1222 }
1223 ASSERT (TopEntry != NULL && BottomEntry != NULL);
1224
1225 //
1226 // Convert/Insert the list of descriptors from StartLink to EndLink
1227 //
1228 Link = StartLink;
1229 while (Link != EndLink->ForwardLink) {
1230 Entry = CR (Link, EFI_GCD_MAP_ENTRY, Link, EFI_GCD_MAP_SIGNATURE);
1231 CoreInsertGcdMapEntry (Link, Entry, *BaseAddress, Length, TopEntry, BottomEntry);
1232 Entry->ImageHandle = ImageHandle;
1233 Entry->DeviceHandle = DeviceHandle;
1234 Link = Link->ForwardLink;
1235 }
1236
1237 //
1238 // Cleanup
1239 //
1240 Status = CoreCleanupGcdMapEntry (TopEntry, BottomEntry, StartLink, EndLink, Map);
1241
1242 Done:
1243 DEBUG ((DEBUG_GCD, " Status = %r", Status));
1244 if (!EFI_ERROR (Status)) {
1245 DEBUG ((DEBUG_GCD, " (BaseAddress = %016lx)", *BaseAddress));
1246 }
1247 DEBUG ((DEBUG_GCD, "\n"));
1248
1249 if ((Operation & GCD_MEMORY_SPACE_OPERATION) != 0) {
1250 CoreReleaseGcdMemoryLock ();
1251 CoreDumpGcdMemorySpaceMap (FALSE);
1252 }
1253 if ((Operation & GCD_IO_SPACE_OPERATION) !=0) {
1254 CoreReleaseGcdIoLock ();
1255 CoreDumpGcdIoSpaceMap (FALSE);
1256 }
1257
1258 return Status;
1259 }
1260
1261
1262 /**
1263 Add a segment of memory to GCD map.
1264
1265 @param GcdMemoryType Memory type of the segment.
1266 @param BaseAddress Base address of the segment.
1267 @param Length Length of the segment.
1268 @param Capabilities alterable attributes of the segment.
1269
1270 @retval EFI_INVALID_PARAMETER Invalid parameters.
1271 @retval EFI_SUCCESS Successfully add a segment of memory space.
1272
1273 **/
1274 EFI_STATUS
1275 CoreInternalAddMemorySpace (
1276 IN EFI_GCD_MEMORY_TYPE GcdMemoryType,
1277 IN EFI_PHYSICAL_ADDRESS BaseAddress,
1278 IN UINT64 Length,
1279 IN UINT64 Capabilities
1280 )
1281 {
1282 DEBUG ((DEBUG_GCD, "GCD:AddMemorySpace(Base=%016lx,Length=%016lx)\n", BaseAddress, Length));
1283 DEBUG ((DEBUG_GCD, " GcdMemoryType = %a\n", mGcdMemoryTypeNames[MIN (GcdMemoryType, EfiGcdMemoryTypeMaximum)]));
1284 DEBUG ((DEBUG_GCD, " Capabilities = %016lx\n", Capabilities));
1285
1286 //
1287 // Make sure parameters are valid
1288 //
1289 if (GcdMemoryType <= EfiGcdMemoryTypeNonExistent || GcdMemoryType >= EfiGcdMemoryTypeMaximum) {
1290 return EFI_INVALID_PARAMETER;
1291 }
1292
1293 return CoreConvertSpace (GCD_ADD_MEMORY_OPERATION, GcdMemoryType, (EFI_GCD_IO_TYPE) 0, BaseAddress, Length, Capabilities, 0);
1294 }
1295
1296 //
1297 // GCD Core Services
1298 //
1299
1300 /**
1301 Allocates nonexistent memory, reserved memory, system memory, or memorymapped
1302 I/O resources from the global coherency domain of the processor.
1303
1304 @param GcdAllocateType The type of allocate operation
1305 @param GcdMemoryType The desired memory type
1306 @param Alignment Align with 2^Alignment
1307 @param Length Length to allocate
1308 @param BaseAddress Base address to allocate
1309 @param ImageHandle The image handle consume the allocated space.
1310 @param DeviceHandle The device handle consume the allocated space.
1311
1312 @retval EFI_INVALID_PARAMETER Invalid parameter.
1313 @retval EFI_NOT_FOUND No descriptor contains the desired space.
1314 @retval EFI_SUCCESS Memory space successfully allocated.
1315
1316 **/
1317 EFI_STATUS
1318 EFIAPI
1319 CoreAllocateMemorySpace (
1320 IN EFI_GCD_ALLOCATE_TYPE GcdAllocateType,
1321 IN EFI_GCD_MEMORY_TYPE GcdMemoryType,
1322 IN UINTN Alignment,
1323 IN UINT64 Length,
1324 IN OUT EFI_PHYSICAL_ADDRESS *BaseAddress,
1325 IN EFI_HANDLE ImageHandle,
1326 IN EFI_HANDLE DeviceHandle OPTIONAL
1327 )
1328 {
1329 DEBUG ((DEBUG_GCD, "GCD:AllocateMemorySpace(Base=%016lx,Length=%016lx)\n", *BaseAddress, Length));
1330 DEBUG ((DEBUG_GCD, " GcdAllocateType = %a\n", mGcdAllocationTypeNames[MIN (GcdAllocateType, EfiGcdMaxAllocateType)]));
1331 DEBUG ((DEBUG_GCD, " GcdMemoryType = %a\n", mGcdMemoryTypeNames[MIN (GcdMemoryType, EfiGcdMemoryTypeMaximum)]));
1332 DEBUG ((DEBUG_GCD, " Alignment = %016lx\n", LShiftU64 (1, Alignment)));
1333 DEBUG ((DEBUG_GCD, " ImageHandle = %p\n", ImageHandle));
1334 DEBUG ((DEBUG_GCD, " DeviceHandle = %p\n", DeviceHandle));
1335
1336 return CoreAllocateSpace (
1337 GCD_ALLOCATE_MEMORY_OPERATION,
1338 GcdAllocateType,
1339 GcdMemoryType,
1340 (EFI_GCD_IO_TYPE) 0,
1341 Alignment,
1342 Length,
1343 BaseAddress,
1344 ImageHandle,
1345 DeviceHandle
1346 );
1347 }
1348
1349
1350 /**
1351 Adds reserved memory, system memory, or memory-mapped I/O resources to the
1352 global coherency domain of the processor.
1353
1354 @param GcdMemoryType Memory type of the memory space.
1355 @param BaseAddress Base address of the memory space.
1356 @param Length Length of the memory space.
1357 @param Capabilities alterable attributes of the memory space.
1358
1359 @retval EFI_SUCCESS Merged this memory space into GCD map.
1360
1361 **/
1362 EFI_STATUS
1363 EFIAPI
1364 CoreAddMemorySpace (
1365 IN EFI_GCD_MEMORY_TYPE GcdMemoryType,
1366 IN EFI_PHYSICAL_ADDRESS BaseAddress,
1367 IN UINT64 Length,
1368 IN UINT64 Capabilities
1369 )
1370 {
1371 EFI_STATUS Status;
1372 EFI_PHYSICAL_ADDRESS PageBaseAddress;
1373 UINT64 PageLength;
1374
1375 Status = CoreInternalAddMemorySpace (GcdMemoryType, BaseAddress, Length, Capabilities);
1376
1377 if (!EFI_ERROR (Status) && GcdMemoryType == EfiGcdMemoryTypeSystemMemory) {
1378
1379 PageBaseAddress = PageAlignLength (BaseAddress);
1380 PageLength = PageAlignLength (BaseAddress + Length - PageBaseAddress);
1381
1382 Status = CoreAllocateMemorySpace (
1383 EfiGcdAllocateAddress,
1384 GcdMemoryType,
1385 EFI_PAGE_SHIFT,
1386 PageLength,
1387 &PageBaseAddress,
1388 gDxeCoreImageHandle,
1389 NULL
1390 );
1391
1392 if (!EFI_ERROR (Status)) {
1393 CoreAddMemoryDescriptor (
1394 EfiConventionalMemory,
1395 PageBaseAddress,
1396 RShiftU64 (PageLength, EFI_PAGE_SHIFT),
1397 Capabilities
1398 );
1399 } else {
1400 for (; PageLength != 0; PageLength -= EFI_PAGE_SIZE, PageBaseAddress += EFI_PAGE_SIZE) {
1401 Status = CoreAllocateMemorySpace (
1402 EfiGcdAllocateAddress,
1403 GcdMemoryType,
1404 EFI_PAGE_SHIFT,
1405 EFI_PAGE_SIZE,
1406 &PageBaseAddress,
1407 gDxeCoreImageHandle,
1408 NULL
1409 );
1410
1411 if (!EFI_ERROR (Status)) {
1412 CoreAddMemoryDescriptor (
1413 EfiConventionalMemory,
1414 PageBaseAddress,
1415 1,
1416 Capabilities
1417 );
1418 }
1419 }
1420 }
1421 }
1422 return Status;
1423 }
1424
1425
1426 /**
1427 Frees nonexistent memory, reserved memory, system memory, or memory-mapped
1428 I/O resources from the global coherency domain of the processor.
1429
1430 @param BaseAddress Base address of the memory space.
1431 @param Length Length of the memory space.
1432
1433 @retval EFI_SUCCESS Space successfully freed.
1434
1435 **/
1436 EFI_STATUS
1437 EFIAPI
1438 CoreFreeMemorySpace (
1439 IN EFI_PHYSICAL_ADDRESS BaseAddress,
1440 IN UINT64 Length
1441 )
1442 {
1443 DEBUG ((DEBUG_GCD, "GCD:FreeMemorySpace(Base=%016lx,Length=%016lx)\n", BaseAddress, Length));
1444
1445 return CoreConvertSpace (GCD_FREE_MEMORY_OPERATION, (EFI_GCD_MEMORY_TYPE) 0, (EFI_GCD_IO_TYPE) 0, BaseAddress, Length, 0, 0);
1446 }
1447
1448
1449 /**
1450 Removes reserved memory, system memory, or memory-mapped I/O resources from
1451 the global coherency domain of the processor.
1452
1453 @param BaseAddress Base address of the memory space.
1454 @param Length Length of the memory space.
1455
1456 @retval EFI_SUCCESS Successfully remove a segment of memory space.
1457
1458 **/
1459 EFI_STATUS
1460 EFIAPI
1461 CoreRemoveMemorySpace (
1462 IN EFI_PHYSICAL_ADDRESS BaseAddress,
1463 IN UINT64 Length
1464 )
1465 {
1466 DEBUG ((DEBUG_GCD, "GCD:RemoveMemorySpace(Base=%016lx,Length=%016lx)\n", BaseAddress, Length));
1467
1468 return CoreConvertSpace (GCD_REMOVE_MEMORY_OPERATION, (EFI_GCD_MEMORY_TYPE) 0, (EFI_GCD_IO_TYPE) 0, BaseAddress, Length, 0, 0);
1469 }
1470
1471
1472 /**
1473 Build a memory descriptor according to an entry.
1474
1475 @param Descriptor The descriptor to be built
1476 @param Entry According to this entry
1477
1478 **/
1479 VOID
1480 BuildMemoryDescriptor (
1481 IN OUT EFI_GCD_MEMORY_SPACE_DESCRIPTOR *Descriptor,
1482 IN EFI_GCD_MAP_ENTRY *Entry
1483 )
1484 {
1485 Descriptor->BaseAddress = Entry->BaseAddress;
1486 Descriptor->Length = Entry->EndAddress - Entry->BaseAddress + 1;
1487 Descriptor->Capabilities = Entry->Capabilities;
1488 Descriptor->Attributes = Entry->Attributes;
1489 Descriptor->GcdMemoryType = Entry->GcdMemoryType;
1490 Descriptor->ImageHandle = Entry->ImageHandle;
1491 Descriptor->DeviceHandle = Entry->DeviceHandle;
1492 }
1493
1494
1495 /**
1496 Retrieves the descriptor for a memory region containing a specified address.
1497
1498 @param BaseAddress Specified start address
1499 @param Descriptor Specified length
1500
1501 @retval EFI_INVALID_PARAMETER Invalid parameter
1502 @retval EFI_SUCCESS Successfully get memory space descriptor.
1503
1504 **/
1505 EFI_STATUS
1506 EFIAPI
1507 CoreGetMemorySpaceDescriptor (
1508 IN EFI_PHYSICAL_ADDRESS BaseAddress,
1509 OUT EFI_GCD_MEMORY_SPACE_DESCRIPTOR *Descriptor
1510 )
1511 {
1512 EFI_STATUS Status;
1513 LIST_ENTRY *StartLink;
1514 LIST_ENTRY *EndLink;
1515 EFI_GCD_MAP_ENTRY *Entry;
1516
1517 //
1518 // Make sure parameters are valid
1519 //
1520 if (Descriptor == NULL) {
1521 return EFI_INVALID_PARAMETER;
1522 }
1523
1524 CoreAcquireGcdMemoryLock ();
1525
1526 //
1527 // Search for the list of descriptors that contain BaseAddress
1528 //
1529 Status = CoreSearchGcdMapEntry (BaseAddress, 1, &StartLink, &EndLink, &mGcdMemorySpaceMap);
1530 if (EFI_ERROR (Status)) {
1531 Status = EFI_NOT_FOUND;
1532 } else {
1533 ASSERT (StartLink != NULL && EndLink != NULL);
1534 //
1535 // Copy the contents of the found descriptor into Descriptor
1536 //
1537 Entry = CR (StartLink, EFI_GCD_MAP_ENTRY, Link, EFI_GCD_MAP_SIGNATURE);
1538 BuildMemoryDescriptor (Descriptor, Entry);
1539 }
1540
1541 CoreReleaseGcdMemoryLock ();
1542
1543 return Status;
1544 }
1545
1546
1547 /**
1548 Modifies the attributes for a memory region in the global coherency domain of the
1549 processor.
1550
1551 @param BaseAddress Specified start address
1552 @param Length Specified length
1553 @param Attributes Specified attributes
1554
1555 @retval EFI_SUCCESS The attributes were set for the memory region.
1556 @retval EFI_INVALID_PARAMETER Length is zero.
1557 @retval EFI_UNSUPPORTED The processor does not support one or more bytes of the memory
1558 resource range specified by BaseAddress and Length.
1559 @retval EFI_UNSUPPORTED The bit mask of attributes is not support for the memory resource
1560 range specified by BaseAddress and Length.
1561 @retval EFI_ACCESS_DEFINED The attributes for the memory resource range specified by
1562 BaseAddress and Length cannot be modified.
1563 @retval EFI_OUT_OF_RESOURCES There are not enough system resources to modify the attributes of
1564 the memory resource range.
1565 @retval EFI_NOT_AVAILABLE_YET The attributes cannot be set because CPU architectural protocol is
1566 not available yet.
1567
1568 **/
1569 EFI_STATUS
1570 EFIAPI
1571 CoreSetMemorySpaceAttributes (
1572 IN EFI_PHYSICAL_ADDRESS BaseAddress,
1573 IN UINT64 Length,
1574 IN UINT64 Attributes
1575 )
1576 {
1577 DEBUG ((DEBUG_GCD, "GCD:SetMemorySpaceAttributes(Base=%016lx,Length=%016lx)\n", BaseAddress, Length));
1578 DEBUG ((DEBUG_GCD, " Attributes = %016lx\n", Attributes));
1579
1580 return CoreConvertSpace (GCD_SET_ATTRIBUTES_MEMORY_OPERATION, (EFI_GCD_MEMORY_TYPE) 0, (EFI_GCD_IO_TYPE) 0, BaseAddress, Length, 0, Attributes);
1581 }
1582
1583
1584 /**
1585 Modifies the capabilities for a memory region in the global coherency domain of the
1586 processor.
1587
1588 @param BaseAddress The physical address that is the start address of a memory region.
1589 @param Length The size in bytes of the memory region.
1590 @param Capabilities The bit mask of capabilities that the memory region supports.
1591
1592 @retval EFI_SUCCESS The capabilities were set for the memory region.
1593 @retval EFI_INVALID_PARAMETER Length is zero.
1594 @retval EFI_UNSUPPORTED The capabilities specified by Capabilities do not include the
1595 memory region attributes currently in use.
1596 @retval EFI_ACCESS_DENIED The capabilities for the memory resource range specified by
1597 BaseAddress and Length cannot be modified.
1598 @retval EFI_OUT_OF_RESOURCES There are not enough system resources to modify the capabilities
1599 of the memory resource range.
1600 **/
1601 EFI_STATUS
1602 EFIAPI
1603 CoreSetMemorySpaceCapabilities (
1604 IN EFI_PHYSICAL_ADDRESS BaseAddress,
1605 IN UINT64 Length,
1606 IN UINT64 Capabilities
1607 )
1608 {
1609 EFI_STATUS Status;
1610
1611 DEBUG ((DEBUG_GCD, "GCD:CoreSetMemorySpaceCapabilities(Base=%016lx,Length=%016lx)\n", BaseAddress, Length));
1612 DEBUG ((DEBUG_GCD, " Capabilities = %016lx\n", Capabilities));
1613
1614 Status = CoreConvertSpace (GCD_SET_CAPABILITIES_MEMORY_OPERATION, (EFI_GCD_MEMORY_TYPE) 0, (EFI_GCD_IO_TYPE) 0, BaseAddress, Length, Capabilities, 0);
1615 if (!EFI_ERROR(Status)) {
1616 CoreUpdateMemoryAttributes(BaseAddress, RShiftU64(Length, EFI_PAGE_SHIFT), Capabilities);
1617 }
1618
1619 return Status;
1620 }
1621
1622
1623 /**
1624 Returns a map of the memory resources in the global coherency domain of the
1625 processor.
1626
1627 @param NumberOfDescriptors Number of descriptors.
1628 @param MemorySpaceMap Descriptor array
1629
1630 @retval EFI_INVALID_PARAMETER Invalid parameter
1631 @retval EFI_OUT_OF_RESOURCES No enough buffer to allocate
1632 @retval EFI_SUCCESS Successfully get memory space map.
1633
1634 **/
1635 EFI_STATUS
1636 EFIAPI
1637 CoreGetMemorySpaceMap (
1638 OUT UINTN *NumberOfDescriptors,
1639 OUT EFI_GCD_MEMORY_SPACE_DESCRIPTOR **MemorySpaceMap
1640 )
1641 {
1642 EFI_STATUS Status;
1643 LIST_ENTRY *Link;
1644 EFI_GCD_MAP_ENTRY *Entry;
1645 EFI_GCD_MEMORY_SPACE_DESCRIPTOR *Descriptor;
1646
1647 //
1648 // Make sure parameters are valid
1649 //
1650 if (NumberOfDescriptors == NULL) {
1651 return EFI_INVALID_PARAMETER;
1652 }
1653 if (MemorySpaceMap == NULL) {
1654 return EFI_INVALID_PARAMETER;
1655 }
1656
1657 CoreAcquireGcdMemoryLock ();
1658
1659 //
1660 // Count the number of descriptors
1661 //
1662 *NumberOfDescriptors = CoreCountGcdMapEntry (&mGcdMemorySpaceMap);
1663
1664 //
1665 // Allocate the MemorySpaceMap
1666 //
1667 *MemorySpaceMap = AllocatePool (*NumberOfDescriptors * sizeof (EFI_GCD_MEMORY_SPACE_DESCRIPTOR));
1668 if (*MemorySpaceMap == NULL) {
1669 Status = EFI_OUT_OF_RESOURCES;
1670 goto Done;
1671 }
1672
1673 //
1674 // Fill in the MemorySpaceMap
1675 //
1676 Descriptor = *MemorySpaceMap;
1677 Link = mGcdMemorySpaceMap.ForwardLink;
1678 while (Link != &mGcdMemorySpaceMap) {
1679 Entry = CR (Link, EFI_GCD_MAP_ENTRY, Link, EFI_GCD_MAP_SIGNATURE);
1680 BuildMemoryDescriptor (Descriptor, Entry);
1681 Descriptor++;
1682 Link = Link->ForwardLink;
1683 }
1684 Status = EFI_SUCCESS;
1685
1686 Done:
1687 CoreReleaseGcdMemoryLock ();
1688 return Status;
1689 }
1690
1691
1692 /**
1693 Adds reserved I/O or I/O resources to the global coherency domain of the processor.
1694
1695 @param GcdIoType IO type of the segment.
1696 @param BaseAddress Base address of the segment.
1697 @param Length Length of the segment.
1698
1699 @retval EFI_SUCCESS Merged this segment into GCD map.
1700 @retval EFI_INVALID_PARAMETER Parameter not valid
1701
1702 **/
1703 EFI_STATUS
1704 EFIAPI
1705 CoreAddIoSpace (
1706 IN EFI_GCD_IO_TYPE GcdIoType,
1707 IN EFI_PHYSICAL_ADDRESS BaseAddress,
1708 IN UINT64 Length
1709 )
1710 {
1711 DEBUG ((DEBUG_GCD, "GCD:AddIoSpace(Base=%016lx,Length=%016lx)\n", BaseAddress, Length));
1712 DEBUG ((DEBUG_GCD, " GcdIoType = %a\n", mGcdIoTypeNames[MIN (GcdIoType, EfiGcdIoTypeMaximum)]));
1713
1714 //
1715 // Make sure parameters are valid
1716 //
1717 if (GcdIoType <= EfiGcdIoTypeNonExistent || GcdIoType >= EfiGcdIoTypeMaximum) {
1718 return EFI_INVALID_PARAMETER;
1719 }
1720 return CoreConvertSpace (GCD_ADD_IO_OPERATION, (EFI_GCD_MEMORY_TYPE) 0, GcdIoType, BaseAddress, Length, 0, 0);
1721 }
1722
1723
1724 /**
1725 Allocates nonexistent I/O, reserved I/O, or I/O resources from the global coherency
1726 domain of the processor.
1727
1728 @param GcdAllocateType The type of allocate operation
1729 @param GcdIoType The desired IO type
1730 @param Alignment Align with 2^Alignment
1731 @param Length Length to allocate
1732 @param BaseAddress Base address to allocate
1733 @param ImageHandle The image handle consume the allocated space.
1734 @param DeviceHandle The device handle consume the allocated space.
1735
1736 @retval EFI_INVALID_PARAMETER Invalid parameter.
1737 @retval EFI_NOT_FOUND No descriptor contains the desired space.
1738 @retval EFI_SUCCESS IO space successfully allocated.
1739
1740 **/
1741 EFI_STATUS
1742 EFIAPI
1743 CoreAllocateIoSpace (
1744 IN EFI_GCD_ALLOCATE_TYPE GcdAllocateType,
1745 IN EFI_GCD_IO_TYPE GcdIoType,
1746 IN UINTN Alignment,
1747 IN UINT64 Length,
1748 IN OUT EFI_PHYSICAL_ADDRESS *BaseAddress,
1749 IN EFI_HANDLE ImageHandle,
1750 IN EFI_HANDLE DeviceHandle OPTIONAL
1751 )
1752 {
1753 DEBUG ((DEBUG_GCD, "GCD:AllocateIoSpace(Base=%016lx,Length=%016lx)\n", *BaseAddress, Length));
1754 DEBUG ((DEBUG_GCD, " GcdAllocateType = %a\n", mGcdAllocationTypeNames[MIN (GcdAllocateType, EfiGcdMaxAllocateType)]));
1755 DEBUG ((DEBUG_GCD, " GcdIoType = %a\n", mGcdIoTypeNames[MIN (GcdIoType, EfiGcdIoTypeMaximum)]));
1756 DEBUG ((DEBUG_GCD, " Alignment = %016lx\n", LShiftU64 (1, Alignment)));
1757 DEBUG ((DEBUG_GCD, " ImageHandle = %p\n", ImageHandle));
1758 DEBUG ((DEBUG_GCD, " DeviceHandle = %p\n", DeviceHandle));
1759
1760 return CoreAllocateSpace (
1761 GCD_ALLOCATE_IO_OPERATION,
1762 GcdAllocateType,
1763 (EFI_GCD_MEMORY_TYPE) 0,
1764 GcdIoType,
1765 Alignment,
1766 Length,
1767 BaseAddress,
1768 ImageHandle,
1769 DeviceHandle
1770 );
1771 }
1772
1773
1774 /**
1775 Frees nonexistent I/O, reserved I/O, or I/O resources from the global coherency
1776 domain of the processor.
1777
1778 @param BaseAddress Base address of the segment.
1779 @param Length Length of the segment.
1780
1781 @retval EFI_SUCCESS Space successfully freed.
1782
1783 **/
1784 EFI_STATUS
1785 EFIAPI
1786 CoreFreeIoSpace (
1787 IN EFI_PHYSICAL_ADDRESS BaseAddress,
1788 IN UINT64 Length
1789 )
1790 {
1791 DEBUG ((DEBUG_GCD, "GCD:FreeIoSpace(Base=%016lx,Length=%016lx)\n", BaseAddress, Length));
1792
1793 return CoreConvertSpace (GCD_FREE_IO_OPERATION, (EFI_GCD_MEMORY_TYPE) 0, (EFI_GCD_IO_TYPE) 0, BaseAddress, Length, 0, 0);
1794 }
1795
1796
1797 /**
1798 Removes reserved I/O or I/O resources from the global coherency domain of the
1799 processor.
1800
1801 @param BaseAddress Base address of the segment.
1802 @param Length Length of the segment.
1803
1804 @retval EFI_SUCCESS Successfully removed a segment of IO space.
1805
1806 **/
1807 EFI_STATUS
1808 EFIAPI
1809 CoreRemoveIoSpace (
1810 IN EFI_PHYSICAL_ADDRESS BaseAddress,
1811 IN UINT64 Length
1812 )
1813 {
1814 DEBUG ((DEBUG_GCD, "GCD:RemoveIoSpace(Base=%016lx,Length=%016lx)\n", BaseAddress, Length));
1815
1816 return CoreConvertSpace (GCD_REMOVE_IO_OPERATION, (EFI_GCD_MEMORY_TYPE) 0, (EFI_GCD_IO_TYPE) 0, BaseAddress, Length, 0, 0);
1817 }
1818
1819
1820 /**
1821 Build a IO descriptor according to an entry.
1822
1823 @param Descriptor The descriptor to be built
1824 @param Entry According to this entry
1825
1826 **/
1827 VOID
1828 BuildIoDescriptor (
1829 IN EFI_GCD_IO_SPACE_DESCRIPTOR *Descriptor,
1830 IN EFI_GCD_MAP_ENTRY *Entry
1831 )
1832 {
1833 Descriptor->BaseAddress = Entry->BaseAddress;
1834 Descriptor->Length = Entry->EndAddress - Entry->BaseAddress + 1;
1835 Descriptor->GcdIoType = Entry->GcdIoType;
1836 Descriptor->ImageHandle = Entry->ImageHandle;
1837 Descriptor->DeviceHandle = Entry->DeviceHandle;
1838 }
1839
1840
1841 /**
1842 Retrieves the descriptor for an I/O region containing a specified address.
1843
1844 @param BaseAddress Specified start address
1845 @param Descriptor Specified length
1846
1847 @retval EFI_INVALID_PARAMETER Descriptor is NULL.
1848 @retval EFI_SUCCESS Successfully get the IO space descriptor.
1849
1850 **/
1851 EFI_STATUS
1852 EFIAPI
1853 CoreGetIoSpaceDescriptor (
1854 IN EFI_PHYSICAL_ADDRESS BaseAddress,
1855 OUT EFI_GCD_IO_SPACE_DESCRIPTOR *Descriptor
1856 )
1857 {
1858 EFI_STATUS Status;
1859 LIST_ENTRY *StartLink;
1860 LIST_ENTRY *EndLink;
1861 EFI_GCD_MAP_ENTRY *Entry;
1862
1863 //
1864 // Make sure parameters are valid
1865 //
1866 if (Descriptor == NULL) {
1867 return EFI_INVALID_PARAMETER;
1868 }
1869
1870 CoreAcquireGcdIoLock ();
1871
1872 //
1873 // Search for the list of descriptors that contain BaseAddress
1874 //
1875 Status = CoreSearchGcdMapEntry (BaseAddress, 1, &StartLink, &EndLink, &mGcdIoSpaceMap);
1876 if (EFI_ERROR (Status)) {
1877 Status = EFI_NOT_FOUND;
1878 } else {
1879 ASSERT (StartLink != NULL && EndLink != NULL);
1880 //
1881 // Copy the contents of the found descriptor into Descriptor
1882 //
1883 Entry = CR (StartLink, EFI_GCD_MAP_ENTRY, Link, EFI_GCD_MAP_SIGNATURE);
1884 BuildIoDescriptor (Descriptor, Entry);
1885 }
1886
1887 CoreReleaseGcdIoLock ();
1888
1889 return Status;
1890 }
1891
1892
1893 /**
1894 Returns a map of the I/O resources in the global coherency domain of the processor.
1895
1896 @param NumberOfDescriptors Number of descriptors.
1897 @param IoSpaceMap Descriptor array
1898
1899 @retval EFI_INVALID_PARAMETER Invalid parameter
1900 @retval EFI_OUT_OF_RESOURCES No enough buffer to allocate
1901 @retval EFI_SUCCESS Successfully get IO space map.
1902
1903 **/
1904 EFI_STATUS
1905 EFIAPI
1906 CoreGetIoSpaceMap (
1907 OUT UINTN *NumberOfDescriptors,
1908 OUT EFI_GCD_IO_SPACE_DESCRIPTOR **IoSpaceMap
1909 )
1910 {
1911 EFI_STATUS Status;
1912 LIST_ENTRY *Link;
1913 EFI_GCD_MAP_ENTRY *Entry;
1914 EFI_GCD_IO_SPACE_DESCRIPTOR *Descriptor;
1915
1916 //
1917 // Make sure parameters are valid
1918 //
1919 if (NumberOfDescriptors == NULL) {
1920 return EFI_INVALID_PARAMETER;
1921 }
1922 if (IoSpaceMap == NULL) {
1923 return EFI_INVALID_PARAMETER;
1924 }
1925
1926 CoreAcquireGcdIoLock ();
1927
1928 //
1929 // Count the number of descriptors
1930 //
1931 *NumberOfDescriptors = CoreCountGcdMapEntry (&mGcdIoSpaceMap);
1932
1933 //
1934 // Allocate the IoSpaceMap
1935 //
1936 *IoSpaceMap = AllocatePool (*NumberOfDescriptors * sizeof (EFI_GCD_IO_SPACE_DESCRIPTOR));
1937 if (*IoSpaceMap == NULL) {
1938 Status = EFI_OUT_OF_RESOURCES;
1939 goto Done;
1940 }
1941
1942 //
1943 // Fill in the IoSpaceMap
1944 //
1945 Descriptor = *IoSpaceMap;
1946 Link = mGcdIoSpaceMap.ForwardLink;
1947 while (Link != &mGcdIoSpaceMap) {
1948 Entry = CR (Link, EFI_GCD_MAP_ENTRY, Link, EFI_GCD_MAP_SIGNATURE);
1949 BuildIoDescriptor (Descriptor, Entry);
1950 Descriptor++;
1951 Link = Link->ForwardLink;
1952 }
1953 Status = EFI_SUCCESS;
1954
1955 Done:
1956 CoreReleaseGcdIoLock ();
1957 return Status;
1958 }
1959
1960
1961 /**
1962 Converts a Resource Descriptor HOB attributes mask to an EFI Memory Descriptor
1963 capabilities mask
1964
1965 @param GcdMemoryType Type of resource in the GCD memory map.
1966 @param Attributes The attribute mask in the Resource Descriptor
1967 HOB.
1968
1969 @return The capabilities mask for an EFI Memory Descriptor.
1970
1971 **/
1972 UINT64
1973 CoreConvertResourceDescriptorHobAttributesToCapabilities (
1974 EFI_GCD_MEMORY_TYPE GcdMemoryType,
1975 UINT64 Attributes
1976 )
1977 {
1978 UINT64 Capabilities;
1979 GCD_ATTRIBUTE_CONVERSION_ENTRY *Conversion;
1980
1981 //
1982 // Convert the Resource HOB Attributes to an EFI Memory Capabilities mask
1983 //
1984 for (Capabilities = 0, Conversion = mAttributeConversionTable; Conversion->Attribute != 0; Conversion++) {
1985 if (Conversion->Memory || (GcdMemoryType != EfiGcdMemoryTypeSystemMemory)) {
1986 if (Attributes & Conversion->Attribute) {
1987 Capabilities |= Conversion->Capability;
1988 }
1989 }
1990 }
1991
1992 return Capabilities;
1993 }
1994
1995
1996 /**
1997 External function. Initializes memory services based on the memory
1998 descriptor HOBs. This function is responsible for priming the memory
1999 map, so memory allocations and resource allocations can be made.
2000 The first part of this function can not depend on any memory services
2001 until at least one memory descriptor is provided to the memory services.
2002
2003 @param HobStart The start address of the HOB.
2004 @param MemoryBaseAddress Start address of memory region found to init DXE
2005 core.
2006 @param MemoryLength Length of memory region found to init DXE core.
2007
2008 @retval EFI_SUCCESS Memory services successfully initialized.
2009
2010 **/
2011 EFI_STATUS
2012 CoreInitializeMemoryServices (
2013 IN VOID **HobStart,
2014 OUT EFI_PHYSICAL_ADDRESS *MemoryBaseAddress,
2015 OUT UINT64 *MemoryLength
2016 )
2017 {
2018 EFI_PEI_HOB_POINTERS Hob;
2019 EFI_MEMORY_TYPE_INFORMATION *EfiMemoryTypeInformation;
2020 UINTN DataSize;
2021 BOOLEAN Found;
2022 EFI_HOB_HANDOFF_INFO_TABLE *PhitHob;
2023 EFI_HOB_RESOURCE_DESCRIPTOR *ResourceHob;
2024 EFI_HOB_RESOURCE_DESCRIPTOR *PhitResourceHob;
2025 EFI_PHYSICAL_ADDRESS BaseAddress;
2026 UINT64 Length;
2027 UINT64 Attributes;
2028 UINT64 Capabilities;
2029 EFI_PHYSICAL_ADDRESS MaxMemoryBaseAddress;
2030 UINT64 MaxMemoryLength;
2031 UINT64 MaxMemoryAttributes;
2032 EFI_PHYSICAL_ADDRESS TestedMemoryBaseAddress;
2033 UINT64 TestedMemoryLength;
2034 EFI_PHYSICAL_ADDRESS HighAddress;
2035 EFI_HOB_GUID_TYPE *GuidHob;
2036 UINT32 ReservedCodePageNumber;
2037
2038 //
2039 // Point at the first HOB. This must be the PHIT HOB.
2040 //
2041 Hob.Raw = *HobStart;
2042 ASSERT (GET_HOB_TYPE (Hob) == EFI_HOB_TYPE_HANDOFF);
2043
2044 //
2045 // Initialize the spin locks and maps in the memory services.
2046 // Also fill in the memory services into the EFI Boot Services Table
2047 //
2048 CoreInitializePool ();
2049
2050 //
2051 // Initialize Local Variables
2052 //
2053 PhitResourceHob = NULL;
2054 ResourceHob = NULL;
2055 BaseAddress = 0;
2056 Length = 0;
2057 Attributes = 0;
2058 MaxMemoryBaseAddress = 0;
2059 MaxMemoryLength = 0;
2060 MaxMemoryAttributes = 0;
2061
2062 //
2063 // Cache the PHIT HOB for later use
2064 //
2065 PhitHob = Hob.HandoffInformationTable;
2066
2067 if (PcdGet64(PcdLoadModuleAtFixAddressEnable) != 0) {
2068 ReservedCodePageNumber = PcdGet32(PcdLoadFixAddressRuntimeCodePageNumber);
2069 ReservedCodePageNumber += PcdGet32(PcdLoadFixAddressBootTimeCodePageNumber);
2070
2071 //
2072 // cache the Top address for loading modules at Fixed Address
2073 //
2074 gLoadModuleAtFixAddressConfigurationTable.DxeCodeTopAddress = PhitHob->EfiMemoryTop
2075 + EFI_PAGES_TO_SIZE(ReservedCodePageNumber);
2076 }
2077 //
2078 // See if a Memory Type Information HOB is available
2079 //
2080 GuidHob = GetFirstGuidHob (&gEfiMemoryTypeInformationGuid);
2081 if (GuidHob != NULL) {
2082 EfiMemoryTypeInformation = GET_GUID_HOB_DATA (GuidHob);
2083 DataSize = GET_GUID_HOB_DATA_SIZE (GuidHob);
2084 if (EfiMemoryTypeInformation != NULL && DataSize > 0 && DataSize <= (EfiMaxMemoryType + 1) * sizeof (EFI_MEMORY_TYPE_INFORMATION)) {
2085 CopyMem (&gMemoryTypeInformation, EfiMemoryTypeInformation, DataSize);
2086 }
2087 }
2088
2089 //
2090 // Find the Resource Descriptor HOB that contains PHIT range EfiFreeMemoryBottom..EfiFreeMemoryTop
2091 //
2092 Length = 0;
2093 Found = FALSE;
2094 for (Hob.Raw = *HobStart; !END_OF_HOB_LIST(Hob); Hob.Raw = GET_NEXT_HOB(Hob)) {
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
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
2113 //
2114 // Skip Resource Descriptor HOBs that do not contain the PHIT range EfiFreeMemoryBottom..EfiFreeMemoryTop
2115 //
2116 if (PhitHob->EfiFreeMemoryBottom < ResourceHob->PhysicalStart) {
2117 continue;
2118 }
2119 if (PhitHob->EfiFreeMemoryTop > (ResourceHob->PhysicalStart + ResourceHob->ResourceLength)) {
2120 continue;
2121 }
2122
2123 //
2124 // Cache the resource descriptor HOB for the memory region described by the PHIT HOB
2125 //
2126 PhitResourceHob = ResourceHob;
2127 Found = TRUE;
2128
2129 //
2130 // Compute range between PHIT EfiFreeMemoryTop and the end of the Resource Descriptor HOB
2131 //
2132 Attributes = PhitResourceHob->ResourceAttribute;
2133 BaseAddress = PageAlignAddress (PhitHob->EfiMemoryTop);
2134 Length = PageAlignLength (ResourceHob->PhysicalStart + ResourceHob->ResourceLength - BaseAddress);
2135 if (Length < MINIMUM_INITIAL_MEMORY_SIZE) {
2136 //
2137 // If that range is not large enough to intialize the DXE Core, then
2138 // Compute range between PHIT EfiFreeMemoryBottom and PHIT EfiFreeMemoryTop
2139 //
2140 BaseAddress = PageAlignAddress (PhitHob->EfiFreeMemoryBottom);
2141 Length = PageAlignLength (PhitHob->EfiFreeMemoryTop - BaseAddress);
2142 if (Length < MINIMUM_INITIAL_MEMORY_SIZE) {
2143 //
2144 // If that range is not large enough to intialize the DXE Core, then
2145 // Compute range between the start of the Resource Descriptor HOB and the start of the HOB List
2146 //
2147 BaseAddress = PageAlignAddress (ResourceHob->PhysicalStart);
2148 Length = PageAlignLength ((UINT64)((UINTN)*HobStart - BaseAddress));
2149 }
2150 }
2151 break;
2152 }
2153
2154 //
2155 // Assert if a resource descriptor HOB for the memory region described by the PHIT was not found
2156 //
2157 ASSERT (Found);
2158
2159 //
2160 // Search all the resource descriptor HOBs from the highest possible addresses down for a memory
2161 // region that is big enough to initialize the DXE core. Always skip the PHIT Resource HOB.
2162 // The max address must be within the physically addressible range for the processor.
2163 //
2164 HighAddress = MAX_ADDRESS;
2165 for (Hob.Raw = *HobStart; !END_OF_HOB_LIST(Hob); Hob.Raw = GET_NEXT_HOB(Hob)) {
2166 //
2167 // Skip the Resource Descriptor HOB that contains the PHIT
2168 //
2169 if (Hob.ResourceDescriptor == PhitResourceHob) {
2170 continue;
2171 }
2172 //
2173 // Skip all HOBs except Resource Descriptor HOBs
2174 //
2175 if (GET_HOB_TYPE (Hob) != EFI_HOB_TYPE_RESOURCE_DESCRIPTOR) {
2176 continue;
2177 }
2178
2179 //
2180 // Skip Resource Descriptor HOBs that do not describe tested system memory below MAX_ADDRESS
2181 //
2182 ResourceHob = Hob.ResourceDescriptor;
2183 if (ResourceHob->ResourceType != EFI_RESOURCE_SYSTEM_MEMORY) {
2184 continue;
2185 }
2186 if ((ResourceHob->ResourceAttribute & MEMORY_ATTRIBUTE_MASK) != TESTED_MEMORY_ATTRIBUTES) {
2187 continue;
2188 }
2189 if ((ResourceHob->PhysicalStart + ResourceHob->ResourceLength) > (EFI_PHYSICAL_ADDRESS)MAX_ADDRESS) {
2190 continue;
2191 }
2192
2193 //
2194 // Skip Resource Descriptor HOBs that are below a previously found Resource Descriptor HOB
2195 //
2196 if (HighAddress != (EFI_PHYSICAL_ADDRESS)MAX_ADDRESS && ResourceHob->PhysicalStart <= HighAddress) {
2197 continue;
2198 }
2199
2200 //
2201 // Skip Resource Descriptor HOBs that are not large enough to initilize the DXE Core
2202 //
2203 TestedMemoryBaseAddress = PageAlignAddress (ResourceHob->PhysicalStart);
2204 TestedMemoryLength = PageAlignLength (ResourceHob->PhysicalStart + ResourceHob->ResourceLength - TestedMemoryBaseAddress);
2205 if (TestedMemoryLength < MINIMUM_INITIAL_MEMORY_SIZE) {
2206 continue;
2207 }
2208
2209 //
2210 // Save the Resource Descriptor HOB context that is large enough to initilize the DXE Core
2211 //
2212 MaxMemoryBaseAddress = TestedMemoryBaseAddress;
2213 MaxMemoryLength = TestedMemoryLength;
2214 MaxMemoryAttributes = ResourceHob->ResourceAttribute;
2215 HighAddress = ResourceHob->PhysicalStart;
2216 }
2217
2218 //
2219 // If Length is not large enough to initialize the DXE Core or a Resource
2220 // Descriptor HOB was found above the PHIT HOB that is large enough to initialize
2221 // the DXE Core, then use the range described by the Resource Descriptor
2222 // HOB that was found above the PHIT HOB.
2223 //
2224 if ((Length < MINIMUM_INITIAL_MEMORY_SIZE) ||
2225 (MaxMemoryBaseAddress > BaseAddress && MaxMemoryLength >= MINIMUM_INITIAL_MEMORY_SIZE)) {
2226 BaseAddress = MaxMemoryBaseAddress;
2227 Length = MaxMemoryLength;
2228 Attributes = MaxMemoryAttributes;
2229 }
2230
2231 //
2232 // If no memory regions are found that are big enough to initialize the DXE core, then ASSERT().
2233 //
2234 ASSERT (Length >= MINIMUM_INITIAL_MEMORY_SIZE);
2235
2236 //
2237 // Convert the Resource HOB Attributes to an EFI Memory Capabilities mask
2238 //
2239 Capabilities = CoreConvertResourceDescriptorHobAttributesToCapabilities (EfiGcdMemoryTypeSystemMemory, Attributes);
2240
2241 //
2242 // Declare the very first memory region, so the EFI Memory Services are available.
2243 //
2244 CoreAddMemoryDescriptor (
2245 EfiConventionalMemory,
2246 BaseAddress,
2247 RShiftU64 (Length, EFI_PAGE_SHIFT),
2248 Capabilities
2249 );
2250
2251 *MemoryBaseAddress = BaseAddress;
2252 *MemoryLength = Length;
2253
2254 return EFI_SUCCESS;
2255 }
2256
2257
2258 /**
2259 External function. Initializes the GCD and memory services based on the memory
2260 descriptor HOBs. This function is responsible for priming the GCD map and the
2261 memory map, so memory allocations and resource allocations can be made. The
2262 HobStart will be relocated to a pool buffer.
2263
2264 @param HobStart The start address of the HOB
2265 @param MemoryBaseAddress Start address of memory region found to init DXE
2266 core.
2267 @param MemoryLength Length of memory region found to init DXE core.
2268
2269 @retval EFI_SUCCESS GCD services successfully initialized.
2270
2271 **/
2272 EFI_STATUS
2273 CoreInitializeGcdServices (
2274 IN OUT VOID **HobStart,
2275 IN EFI_PHYSICAL_ADDRESS MemoryBaseAddress,
2276 IN UINT64 MemoryLength
2277 )
2278 {
2279 EFI_PEI_HOB_POINTERS Hob;
2280 VOID *NewHobList;
2281 EFI_HOB_HANDOFF_INFO_TABLE *PhitHob;
2282 UINT8 SizeOfMemorySpace;
2283 UINT8 SizeOfIoSpace;
2284 EFI_HOB_RESOURCE_DESCRIPTOR *ResourceHob;
2285 EFI_PHYSICAL_ADDRESS BaseAddress;
2286 UINT64 Length;
2287 EFI_STATUS Status;
2288 EFI_GCD_MAP_ENTRY *Entry;
2289 EFI_GCD_MEMORY_TYPE GcdMemoryType;
2290 EFI_GCD_IO_TYPE GcdIoType;
2291 EFI_GCD_MEMORY_SPACE_DESCRIPTOR Descriptor;
2292 EFI_HOB_MEMORY_ALLOCATION *MemoryHob;
2293 EFI_HOB_FIRMWARE_VOLUME *FirmwareVolumeHob;
2294 UINTN NumberOfDescriptors;
2295 EFI_GCD_MEMORY_SPACE_DESCRIPTOR *MemorySpaceMap;
2296 UINTN Index;
2297 UINT64 Capabilities;
2298 EFI_HOB_CPU * CpuHob;
2299
2300 //
2301 // Cache the PHIT HOB for later use
2302 //
2303 PhitHob = (EFI_HOB_HANDOFF_INFO_TABLE *)(*HobStart);
2304
2305 //
2306 // Get the number of address lines in the I/O and Memory space for the CPU
2307 //
2308 CpuHob = GetFirstHob (EFI_HOB_TYPE_CPU);
2309 ASSERT (CpuHob != NULL);
2310 SizeOfMemorySpace = CpuHob->SizeOfMemorySpace;
2311 SizeOfIoSpace = CpuHob->SizeOfIoSpace;
2312
2313 //
2314 // Initialize the GCD Memory Space Map
2315 //
2316 Entry = AllocateCopyPool (sizeof (EFI_GCD_MAP_ENTRY), &mGcdMemorySpaceMapEntryTemplate);
2317 ASSERT (Entry != NULL);
2318
2319 Entry->EndAddress = LShiftU64 (1, SizeOfMemorySpace) - 1;
2320
2321 InsertHeadList (&mGcdMemorySpaceMap, &Entry->Link);
2322
2323 CoreDumpGcdMemorySpaceMap (TRUE);
2324
2325 //
2326 // Initialize the GCD I/O Space Map
2327 //
2328 Entry = AllocateCopyPool (sizeof (EFI_GCD_MAP_ENTRY), &mGcdIoSpaceMapEntryTemplate);
2329 ASSERT (Entry != NULL);
2330
2331 Entry->EndAddress = LShiftU64 (1, SizeOfIoSpace) - 1;
2332
2333 InsertHeadList (&mGcdIoSpaceMap, &Entry->Link);
2334
2335 CoreDumpGcdIoSpaceMap (TRUE);
2336
2337 //
2338 // Walk the HOB list and add all resource descriptors to the GCD
2339 //
2340 for (Hob.Raw = *HobStart; !END_OF_HOB_LIST(Hob); Hob.Raw = GET_NEXT_HOB(Hob)) {
2341
2342 GcdMemoryType = EfiGcdMemoryTypeNonExistent;
2343 GcdIoType = EfiGcdIoTypeNonExistent;
2344
2345 if (GET_HOB_TYPE (Hob) == EFI_HOB_TYPE_RESOURCE_DESCRIPTOR) {
2346
2347 ResourceHob = Hob.ResourceDescriptor;
2348
2349 switch (ResourceHob->ResourceType) {
2350 case EFI_RESOURCE_SYSTEM_MEMORY:
2351 if ((ResourceHob->ResourceAttribute & MEMORY_ATTRIBUTE_MASK) == TESTED_MEMORY_ATTRIBUTES) {
2352 GcdMemoryType = EfiGcdMemoryTypeSystemMemory;
2353 }
2354 if ((ResourceHob->ResourceAttribute & MEMORY_ATTRIBUTE_MASK) == INITIALIZED_MEMORY_ATTRIBUTES) {
2355 GcdMemoryType = EfiGcdMemoryTypeReserved;
2356 }
2357 if ((ResourceHob->ResourceAttribute & MEMORY_ATTRIBUTE_MASK) == PRESENT_MEMORY_ATTRIBUTES) {
2358 GcdMemoryType = EfiGcdMemoryTypeReserved;
2359 }
2360 break;
2361 case EFI_RESOURCE_MEMORY_MAPPED_IO:
2362 case EFI_RESOURCE_FIRMWARE_DEVICE:
2363 GcdMemoryType = EfiGcdMemoryTypeMemoryMappedIo;
2364 break;
2365 case EFI_RESOURCE_MEMORY_MAPPED_IO_PORT:
2366 case EFI_RESOURCE_MEMORY_RESERVED:
2367 GcdMemoryType = EfiGcdMemoryTypeReserved;
2368 break;
2369 case EFI_RESOURCE_IO:
2370 GcdIoType = EfiGcdIoTypeIo;
2371 break;
2372 case EFI_RESOURCE_IO_RESERVED:
2373 GcdIoType = EfiGcdIoTypeReserved;
2374 break;
2375 }
2376
2377 if (GcdMemoryType != EfiGcdMemoryTypeNonExistent) {
2378 //
2379 // Validate the Resource HOB Attributes
2380 //
2381 CoreValidateResourceDescriptorHobAttributes (ResourceHob->ResourceAttribute);
2382
2383 //
2384 // Convert the Resource HOB Attributes to an EFI Memory Capabilities mask
2385 //
2386 Capabilities = CoreConvertResourceDescriptorHobAttributesToCapabilities (
2387 GcdMemoryType,
2388 ResourceHob->ResourceAttribute
2389 );
2390
2391 Status = CoreInternalAddMemorySpace (
2392 GcdMemoryType,
2393 ResourceHob->PhysicalStart,
2394 ResourceHob->ResourceLength,
2395 Capabilities
2396 );
2397 }
2398
2399 if (GcdIoType != EfiGcdIoTypeNonExistent) {
2400 Status = CoreAddIoSpace (
2401 GcdIoType,
2402 ResourceHob->PhysicalStart,
2403 ResourceHob->ResourceLength
2404 );
2405 }
2406 }
2407 }
2408
2409 //
2410 // Allocate first memory region from the GCD by the DXE core
2411 //
2412 Status = CoreAllocateMemorySpace (
2413 EfiGcdAllocateAddress,
2414 EfiGcdMemoryTypeSystemMemory,
2415 0,
2416 MemoryLength,
2417 &MemoryBaseAddress,
2418 gDxeCoreImageHandle,
2419 NULL
2420 );
2421
2422 //
2423 // Walk the HOB list and allocate all memory space that is consumed by memory allocation HOBs,
2424 // and Firmware Volume HOBs. Also update the EFI Memory Map with the memory allocation HOBs.
2425 //
2426 for (Hob.Raw = *HobStart; !END_OF_HOB_LIST(Hob); Hob.Raw = GET_NEXT_HOB(Hob)) {
2427 if (GET_HOB_TYPE (Hob) == EFI_HOB_TYPE_MEMORY_ALLOCATION) {
2428 MemoryHob = Hob.MemoryAllocation;
2429 BaseAddress = MemoryHob->AllocDescriptor.MemoryBaseAddress;
2430 Status = CoreGetMemorySpaceDescriptor (BaseAddress, &Descriptor);
2431 if (!EFI_ERROR (Status)) {
2432 Status = CoreAllocateMemorySpace (
2433 EfiGcdAllocateAddress,
2434 Descriptor.GcdMemoryType,
2435 0,
2436 MemoryHob->AllocDescriptor.MemoryLength,
2437 &BaseAddress,
2438 gDxeCoreImageHandle,
2439 NULL
2440 );
2441 if (!EFI_ERROR (Status) && Descriptor.GcdMemoryType == EfiGcdMemoryTypeSystemMemory) {
2442 CoreAddMemoryDescriptor (
2443 MemoryHob->AllocDescriptor.MemoryType,
2444 MemoryHob->AllocDescriptor.MemoryBaseAddress,
2445 RShiftU64 (MemoryHob->AllocDescriptor.MemoryLength, EFI_PAGE_SHIFT),
2446 Descriptor.Capabilities & (~EFI_MEMORY_RUNTIME)
2447 );
2448 }
2449 }
2450 }
2451
2452 if (GET_HOB_TYPE (Hob) == EFI_HOB_TYPE_FV) {
2453 FirmwareVolumeHob = Hob.FirmwareVolume;
2454 BaseAddress = FirmwareVolumeHob->BaseAddress;
2455 Status = CoreAllocateMemorySpace (
2456 EfiGcdAllocateAddress,
2457 EfiGcdMemoryTypeMemoryMappedIo,
2458 0,
2459 FirmwareVolumeHob->Length,
2460 &BaseAddress,
2461 gDxeCoreImageHandle,
2462 NULL
2463 );
2464 }
2465 }
2466
2467 //
2468 // Relocate HOB List to an allocated pool buffer.
2469 //
2470 NewHobList = AllocateCopyPool (
2471 (UINTN)PhitHob->EfiFreeMemoryBottom - (UINTN)(*HobStart),
2472 *HobStart
2473 );
2474 ASSERT (NewHobList != NULL);
2475
2476 *HobStart = NewHobList;
2477 gHobList = NewHobList;
2478
2479 //
2480 // Add and allocate the remaining unallocated system memory to the memory services.
2481 //
2482 Status = CoreGetMemorySpaceMap (&NumberOfDescriptors, &MemorySpaceMap);
2483 ASSERT (Status == EFI_SUCCESS);
2484
2485 for (Index = 0; Index < NumberOfDescriptors; Index++) {
2486 if (MemorySpaceMap[Index].GcdMemoryType == EfiGcdMemoryTypeSystemMemory) {
2487 if (MemorySpaceMap[Index].ImageHandle == NULL) {
2488 BaseAddress = PageAlignAddress (MemorySpaceMap[Index].BaseAddress);
2489 Length = PageAlignLength (MemorySpaceMap[Index].BaseAddress + MemorySpaceMap[Index].Length - BaseAddress);
2490 if (Length == 0 || MemorySpaceMap[Index].BaseAddress + MemorySpaceMap[Index].Length < BaseAddress) {
2491 continue;
2492 }
2493 CoreAddMemoryDescriptor (
2494 EfiConventionalMemory,
2495 BaseAddress,
2496 RShiftU64 (Length, EFI_PAGE_SHIFT),
2497 MemorySpaceMap[Index].Capabilities & (~EFI_MEMORY_RUNTIME)
2498 );
2499 Status = CoreAllocateMemorySpace (
2500 EfiGcdAllocateAddress,
2501 EfiGcdMemoryTypeSystemMemory,
2502 0,
2503 Length,
2504 &BaseAddress,
2505 gDxeCoreImageHandle,
2506 NULL
2507 );
2508 }
2509 }
2510 }
2511 CoreFreePool (MemorySpaceMap);
2512
2513 return EFI_SUCCESS;
2514 }