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