TianoCore EDK2 master
Loading...
Searching...
No Matches
Page.c
Go to the documentation of this file.
1
9#include "DxeMain.h"
10#include "Imem.h"
11#include "HeapGuard.h"
12#include <Pi/PiDxeCis.h>
13
14//
15// Entry for tracking the memory regions for each memory type to coalesce similar memory types
16//
17typedef struct {
18 EFI_PHYSICAL_ADDRESS BaseAddress;
19 EFI_PHYSICAL_ADDRESS MaximumAddress;
20 UINT64 CurrentNumberOfPages;
21 UINT64 NumberOfPages;
22 UINTN InformationIndex;
23 BOOLEAN Special;
24 BOOLEAN Runtime;
26
27//
28// MemoryMap - The current memory map
29//
30UINTN mMemoryMapKey = 0;
31
32#define MAX_MAP_DEPTH 6
33
41MEMORY_MAP mMapStack[MAX_MAP_DEPTH];
42UINTN mFreeMapStack = 0;
47BOOLEAN mMemoryTypeInformationInitialized = FALSE;
48
49EFI_MEMORY_TYPE_STATISTICS mMemoryTypeStatistics[EfiMaxMemoryType + 1] = {
50 { 0, MAX_ALLOC_ADDRESS, 0, 0, EfiMaxMemoryType, TRUE, FALSE }, // EfiReservedMemoryType
51 { 0, MAX_ALLOC_ADDRESS, 0, 0, EfiMaxMemoryType, FALSE, FALSE }, // EfiLoaderCode
52 { 0, MAX_ALLOC_ADDRESS, 0, 0, EfiMaxMemoryType, FALSE, FALSE }, // EfiLoaderData
53 { 0, MAX_ALLOC_ADDRESS, 0, 0, EfiMaxMemoryType, FALSE, FALSE }, // EfiBootServicesCode
54 { 0, MAX_ALLOC_ADDRESS, 0, 0, EfiMaxMemoryType, FALSE, FALSE }, // EfiBootServicesData
55 { 0, MAX_ALLOC_ADDRESS, 0, 0, EfiMaxMemoryType, TRUE, TRUE }, // EfiRuntimeServicesCode
56 { 0, MAX_ALLOC_ADDRESS, 0, 0, EfiMaxMemoryType, TRUE, TRUE }, // EfiRuntimeServicesData
57 { 0, MAX_ALLOC_ADDRESS, 0, 0, EfiMaxMemoryType, FALSE, FALSE }, // EfiConventionalMemory
58 { 0, MAX_ALLOC_ADDRESS, 0, 0, EfiMaxMemoryType, FALSE, FALSE }, // EfiUnusableMemory
59 { 0, MAX_ALLOC_ADDRESS, 0, 0, EfiMaxMemoryType, TRUE, FALSE }, // EfiACPIReclaimMemory
60 { 0, MAX_ALLOC_ADDRESS, 0, 0, EfiMaxMemoryType, TRUE, FALSE }, // EfiACPIMemoryNVS
61 { 0, MAX_ALLOC_ADDRESS, 0, 0, EfiMaxMemoryType, FALSE, FALSE }, // EfiMemoryMappedIO
62 { 0, MAX_ALLOC_ADDRESS, 0, 0, EfiMaxMemoryType, FALSE, FALSE }, // EfiMemoryMappedIOPortSpace
63 { 0, MAX_ALLOC_ADDRESS, 0, 0, EfiMaxMemoryType, TRUE, TRUE }, // EfiPalCode
64 { 0, MAX_ALLOC_ADDRESS, 0, 0, EfiMaxMemoryType, FALSE, FALSE }, // EfiPersistentMemory
65 { 0, MAX_ALLOC_ADDRESS, 0, 0, EfiMaxMemoryType, TRUE, FALSE }, // EfiUnacceptedMemoryType
66 { 0, MAX_ALLOC_ADDRESS, 0, 0, EfiMaxMemoryType, FALSE, FALSE } // EfiMaxMemoryType
67};
68
69EFI_PHYSICAL_ADDRESS mDefaultMaximumAddress = MAX_ALLOC_ADDRESS;
70EFI_PHYSICAL_ADDRESS mDefaultBaseAddress = MAX_ALLOC_ADDRESS;
71
72EFI_MEMORY_TYPE_INFORMATION gMemoryTypeInformation[EfiMaxMemoryType + 1] = {
74 { EfiLoaderCode, 0 },
75 { EfiLoaderData, 0 },
81 { EfiUnusableMemory, 0 },
83 { EfiACPIMemoryNVS, 0 },
84 { EfiMemoryMappedIO, 0 },
86 { EfiPalCode, 0 },
89 { EfiMaxMemoryType, 0 }
90};
91//
92// Only used when load module at fixed address feature is enabled. True means the memory is alreay successfully allocated
93// and ready to load the module in to specified address.or else, the memory is not ready and module will be loaded at a
94// address assigned by DXE core.
95//
96GLOBAL_REMOVE_IF_UNREFERENCED BOOLEAN gLoadFixedAddressCodeMemoryReady = FALSE;
97
102VOID
104 VOID
105 )
106{
107 CoreAcquireLock (&gMemoryLock);
108}
109
114VOID
116 VOID
117 )
118{
119 CoreReleaseLock (&gMemoryLock);
120}
121
128VOID
130 IN OUT MEMORY_MAP *Entry
131 )
132{
133 RemoveEntryList (&Entry->Link);
134 Entry->Link.ForwardLink = NULL;
135
136 if (Entry->FromPages) {
137 //
138 // Insert the free memory map descriptor to the end of mFreeMemoryMapEntryList
139 //
141 }
142}
143
156VOID
158 IN EFI_MEMORY_TYPE Type,
161 IN UINT64 Attribute
162 )
163{
164 LIST_ENTRY *Link;
165 MEMORY_MAP *Entry;
166
167 ASSERT ((Start & EFI_PAGE_MASK) == 0);
168 ASSERT (End > Start);
169
170 ASSERT_LOCKED (&gMemoryLock);
171
172 DEBUG ((DEBUG_PAGE, "AddRange: %lx-%lx to %d\n", Start, End, Type));
173
174 //
175 // If memory of type EfiConventionalMemory is being added that includes the page
176 // starting at address 0, then zero the page starting at address 0. This has
177 // two benifits. It helps find NULL pointer bugs and it also maximizes
178 // compatibility with operating systems that may evaluate memory in this page
179 // for legacy data structures. If memory of any other type is added starting
180 // at address 0, then do not zero the page at address 0 because the page is being
181 // used for other purposes.
182 //
183 if ((Type == EfiConventionalMemory) && (Start == 0) && (End >= EFI_PAGE_SIZE - 1)) {
184 if ((PcdGet8 (PcdNullPointerDetectionPropertyMask) & BIT0) == 0) {
185 SetMem ((VOID *)(UINTN)Start, EFI_PAGE_SIZE, 0);
186 }
187 }
188
189 //
190 // Memory map being altered so updated key
191 //
192 mMemoryMapKey += 1;
193
194 //
195 // UEFI 2.0 added an event group for notificaiton on memory map changes.
196 // So we need to signal this Event Group every time the memory map changes.
197 // If we are in EFI 1.10 compatability mode no event groups will be
198 // found and nothing will happen we we call this function. These events
199 // will get signaled but since a lock is held around the call to this
200 // function the notificaiton events will only be called after this function
201 // returns and the lock is released.
202 //
203 CoreNotifySignalList (&gEfiEventMemoryMapChangeGuid);
204
205 //
206 // Look for adjoining memory descriptor
207 //
208
209 // Two memory descriptors can only be merged if they have the same Type
210 // and the same Attribute
211 //
212
213 Link = gMemoryMap.ForwardLink;
214 while (Link != &gMemoryMap) {
215 Entry = CR (Link, MEMORY_MAP, Link, MEMORY_MAP_SIGNATURE);
216 Link = Link->ForwardLink;
217
218 if (Entry->Type != Type) {
219 continue;
220 }
221
222 if (Entry->Attribute != Attribute) {
223 continue;
224 }
225
226 if (Entry->End + 1 == Start) {
227 Start = Entry->Start;
228 RemoveMemoryMapEntry (Entry);
229 } else if (Entry->Start == End + 1) {
230 End = Entry->End;
231 RemoveMemoryMapEntry (Entry);
232 }
233 }
234
235 //
236 // Add descriptor
237 //
238
239 mMapStack[mMapDepth].Signature = MEMORY_MAP_SIGNATURE;
240 mMapStack[mMapDepth].FromPages = FALSE;
241 mMapStack[mMapDepth].Type = Type;
242 mMapStack[mMapDepth].Start = Start;
243 mMapStack[mMapDepth].End = End;
244 mMapStack[mMapDepth].VirtualStart = 0;
245 mMapStack[mMapDepth].Attribute = Attribute;
246 InsertTailList (&gMemoryMap, &mMapStack[mMapDepth].Link);
247
248 mMapDepth += 1;
249 ASSERT (mMapDepth < MAX_MAP_DEPTH);
250
251 return;
252}
253
269 VOID
270 )
271{
272 MEMORY_MAP *FreeDescriptorEntries;
273 MEMORY_MAP *Entry;
274 UINTN Index;
275
277 //
278 // The list is empty, to allocate one page to refuel the list
279 //
280 FreeDescriptorEntries = CoreAllocatePoolPages (
284 FALSE
285 );
286 if (FreeDescriptorEntries != NULL) {
287 //
288 // Enque the free memmory map entries into the list
289 //
290 for (Index = 0; Index < DEFAULT_PAGE_ALLOCATION_GRANULARITY / sizeof (MEMORY_MAP); Index++) {
291 FreeDescriptorEntries[Index].Signature = MEMORY_MAP_SIGNATURE;
292 InsertTailList (&mFreeMemoryMapEntryList, &FreeDescriptorEntries[Index].Link);
293 }
294 } else {
295 return NULL;
296 }
297 }
298
299 //
300 // dequeue the first descriptor from the list
301 //
302 Entry = CR (mFreeMemoryMapEntryList.ForwardLink, MEMORY_MAP, Link, MEMORY_MAP_SIGNATURE);
303 RemoveEntryList (&Entry->Link);
304
305 return Entry;
306}
307
313VOID
315 VOID
316 )
317{
318 MEMORY_MAP *Entry;
319 MEMORY_MAP *Entry2;
320 LIST_ENTRY *Link2;
321
322 ASSERT_LOCKED (&gMemoryLock);
323
324 //
325 // If already freeing the map stack, then return
326 //
327 if (mFreeMapStack != 0) {
328 return;
329 }
330
331 //
332 // Move the temporary memory descriptor stack into pool
333 //
334 mFreeMapStack += 1;
335
336 while (mMapDepth != 0) {
337 //
338 // Deque an memory map entry from mFreeMemoryMapEntryList
339 //
340 Entry = AllocateMemoryMapEntry ();
341
342 // If entry allocation failed once, it is unlikely to succeed moving forward
343 // However, we can try since we're in the middle of moving list nodes
344 if (Entry == NULL) {
345 ASSERT (Entry != NULL);
346 continue;
347 }
348
349 //
350 // Update to proper entry
351 //
352 mMapDepth -= 1;
353
354 if (mMapStack[mMapDepth].Link.ForwardLink != NULL) {
355 //
356 // Move this entry to general memory
357 //
359 mMapStack[mMapDepth].Link.ForwardLink = NULL;
360
361 CopyMem (Entry, &mMapStack[mMapDepth], sizeof (MEMORY_MAP));
362 Entry->FromPages = TRUE;
363
364 //
365 // Find insertion location
366 //
367 for (Link2 = gMemoryMap.ForwardLink; Link2 != &gMemoryMap; Link2 = Link2->ForwardLink) {
368 Entry2 = CR (Link2, MEMORY_MAP, Link, MEMORY_MAP_SIGNATURE);
369 if (Entry2->FromPages && (Entry2->Start > Entry->Start)) {
370 break;
371 }
372 }
373
374 InsertTailList (Link2, &Entry->Link);
375 } else {
376 //
377 // This item of mMapStack[mMapDepth] has already been dequeued from gMemoryMap list,
378 // so here no need to move it to memory.
379 //
381 }
382 }
383
384 mFreeMapStack -= 1;
385}
386
391BOOLEAN
393 VOID
394 )
395{
396 LIST_ENTRY *Link;
397 EFI_GCD_MAP_ENTRY *Entry;
398 BOOLEAN Promoted;
399 EFI_PHYSICAL_ADDRESS StartAddress;
400 EFI_PHYSICAL_ADDRESS EndAddress;
402
403 DEBUG ((DEBUG_PAGE, "Promote the memory resource\n"));
404
406
407 Promoted = FALSE;
408 Link = mGcdMemorySpaceMap.ForwardLink;
409 while (Link != &mGcdMemorySpaceMap) {
410 Entry = CR (Link, EFI_GCD_MAP_ENTRY, Link, EFI_GCD_MAP_SIGNATURE);
411
412 if ((Entry->GcdMemoryType == EfiGcdMemoryTypeReserved) &&
413 (Entry->EndAddress < MAX_ALLOC_ADDRESS) &&
414 ((Entry->Capabilities & (EFI_MEMORY_PRESENT | EFI_MEMORY_INITIALIZED | EFI_MEMORY_TESTED)) ==
415 (EFI_MEMORY_PRESENT | EFI_MEMORY_INITIALIZED)))
416 {
417 //
418 // Update the GCD map
419 //
420 if ((Entry->Capabilities & EFI_MEMORY_MORE_RELIABLE) == EFI_MEMORY_MORE_RELIABLE) {
421 Entry->GcdMemoryType = EfiGcdMemoryTypeMoreReliable;
422 } else {
423 Entry->GcdMemoryType = EfiGcdMemoryTypeSystemMemory;
424 }
425
426 Entry->Capabilities |= EFI_MEMORY_TESTED;
427 Entry->ImageHandle = gDxeCoreImageHandle;
428 Entry->DeviceHandle = NULL;
429
430 //
431 // Add to allocable system memory resource
432 //
433
436 Entry->BaseAddress,
437 Entry->EndAddress,
438 Entry->Capabilities & ~(EFI_MEMORY_PRESENT | EFI_MEMORY_INITIALIZED | EFI_MEMORY_TESTED | EFI_MEMORY_RUNTIME)
439 );
441
442 Promoted = TRUE;
443 }
444
445 Link = Link->ForwardLink;
446 }
447
449
450 if (!Promoted) {
451 //
452 // If freed-memory guard is enabled, we could promote pages from
453 // guarded free pages.
454 //
455 Promoted = PromoteGuardedFreePages (&StartAddress, &EndAddress);
456 if (Promoted) {
457 if (!EFI_ERROR (CoreGetMemorySpaceDescriptor (StartAddress, &Descriptor))) {
460 StartAddress,
461 EndAddress,
462 Descriptor.Capabilities & ~(EFI_MEMORY_PRESENT | EFI_MEMORY_INITIALIZED |
463 EFI_MEMORY_TESTED | EFI_MEMORY_RUNTIME)
464 );
465 }
466 }
467 }
468
469 return Promoted;
470}
471
478VOID
480 VOID
481 )
482{
483 UINT32 RuntimeCodePageNumber;
484 UINT32 BootTimeCodePageNumber;
485 EFI_PHYSICAL_ADDRESS RuntimeCodeBase;
486 EFI_PHYSICAL_ADDRESS BootTimeCodeBase;
487 EFI_STATUS Status;
488
489 //
490 // Make sure these 2 areas are not initialzied.
491 //
492 if (!gLoadFixedAddressCodeMemoryReady) {
493 RuntimeCodePageNumber = PcdGet32 (PcdLoadFixAddressRuntimeCodePageNumber);
494 BootTimeCodePageNumber = PcdGet32 (PcdLoadFixAddressBootTimeCodePageNumber);
495 RuntimeCodeBase = (EFI_PHYSICAL_ADDRESS)(gLoadModuleAtFixAddressConfigurationTable.DxeCodeTopAddress - EFI_PAGES_TO_SIZE (RuntimeCodePageNumber));
496 BootTimeCodeBase = (EFI_PHYSICAL_ADDRESS)(RuntimeCodeBase - EFI_PAGES_TO_SIZE (BootTimeCodePageNumber));
497 //
498 // Try to allocate runtime memory.
499 //
500 Status = CoreAllocatePages (
503 RuntimeCodePageNumber,
504 &RuntimeCodeBase
505 );
506 if (EFI_ERROR (Status)) {
507 //
508 // Runtime memory allocation failed
509 //
510 return;
511 }
512
513 //
514 // Try to allocate boot memory.
515 //
516 Status = CoreAllocatePages (
519 BootTimeCodePageNumber,
520 &BootTimeCodeBase
521 );
522 if (EFI_ERROR (Status)) {
523 //
524 // boot memory allocation failed. Free Runtime code range and will try the allocation again when
525 // new memory range is installed.
526 //
528 RuntimeCodeBase,
529 RuntimeCodePageNumber
530 );
531 return;
532 }
533
534 gLoadFixedAddressCodeMemoryReady = TRUE;
535 }
536
537 return;
538}
539
551VOID
554 IN UINT64 Length
555 )
556{
558 EFI_MEMORY_TYPE Type;
559 UINTN Index;
560 UINT64 Size;
561 UINT64 Alignment;
562 UINT64 BinSize;
563
564 //
565 // Return if Memory Type Information bin locations have already been set
566 //
567 if (mMemoryTypeInformationInitialized) {
568 DEBUG ((DEBUG_ERROR, "%a: Ignored. Bins already set.\n", __func__));
569 return;
570 }
571
572 //
573 // Return if size of the Memory Type Information bins is greater than Length
574 //
575 Top = Start + Length;
576 Size = 0;
577 for (Index = 0; gMemoryTypeInformation[Index].Type != EfiMaxMemoryType; Index++) {
578 //
579 // Make sure the memory type in the gMemoryTypeInformation[] array is valid
580 //
581 Type = (EFI_MEMORY_TYPE)(gMemoryTypeInformation[Index].Type);
582 if ((UINT32)Type > EfiMaxMemoryType) {
583 continue;
584 }
585
586 if (gMemoryTypeInformation[Index].NumberOfPages != 0) {
588 if ((gMemoryTypeInformation[Index].Type == EfiReservedMemoryType) ||
589 (gMemoryTypeInformation[Index].Type == EfiACPIMemoryNVS) ||
590 (gMemoryTypeInformation[Index].Type == EfiRuntimeServicesCode) ||
591 (gMemoryTypeInformation[Index].Type == EfiRuntimeServicesData))
592 {
593 Alignment = RUNTIME_PAGE_ALLOCATION_GRANULARITY;
594 }
595
596 BinSize = EFI_PAGES_TO_SIZE ((UINTN)gMemoryTypeInformation[Index].NumberOfPages);
597 BinSize = ALIGN_VALUE (BinSize, Alignment);
598
599 Size += BinSize;
600 if (Size > Length) {
601 return;
602 }
603
604 Top -= BinSize;
605
606 Size += (Top & (Alignment - 1));
607 if (Size > Length) {
608 return;
609 }
610
611 Top &= ~(Alignment - 1);
612 }
613 }
614
615 if (Size > Length) {
616 return;
617 }
618
619 //
620 // Loop through each memory type in the order specified by the
621 // gMemoryTypeInformation[] array
622 //
623 Top = Start + Length;
624 for (Index = 0; gMemoryTypeInformation[Index].Type != EfiMaxMemoryType; Index++) {
625 //
626 // Make sure the memory type in the gMemoryTypeInformation[] array is valid
627 //
628 Type = (EFI_MEMORY_TYPE)(gMemoryTypeInformation[Index].Type);
629 if ((UINT32)Type > EfiMaxMemoryType) {
630 continue;
631 }
632
633 if (gMemoryTypeInformation[Index].NumberOfPages != 0) {
635 if ((gMemoryTypeInformation[Index].Type == EfiReservedMemoryType) ||
636 (gMemoryTypeInformation[Index].Type == EfiACPIMemoryNVS) ||
637 (gMemoryTypeInformation[Index].Type == EfiRuntimeServicesCode) ||
638 (gMemoryTypeInformation[Index].Type == EfiRuntimeServicesData))
639 {
640 Alignment = RUNTIME_PAGE_ALLOCATION_GRANULARITY;
641 }
642
643 BinSize = EFI_PAGES_TO_SIZE ((UINTN)gMemoryTypeInformation[Index].NumberOfPages);
644 BinSize = ALIGN_VALUE (BinSize, Alignment);
645
646 Top = (Top - BinSize) & ~(Alignment - 1);
647
648 mMemoryTypeStatistics[Type].BaseAddress = Top;
649 mMemoryTypeStatistics[Type].MaximumAddress = Top + BinSize - 1;
650
651 //
652 // If the current base address is the lowest address so far, then update
653 // the default maximum address
654 //
655 if (mMemoryTypeStatistics[Type].BaseAddress < mDefaultMaximumAddress) {
656 mDefaultMaximumAddress = mMemoryTypeStatistics[Type].BaseAddress - 1;
657 }
658
659 mMemoryTypeStatistics[Type].NumberOfPages = EFI_SIZE_TO_PAGES ((UINTN)BinSize);
660 gMemoryTypeInformation[Index].NumberOfPages = 0;
661 }
662 }
663
664 //
665 // If the number of pages reserved for a memory type is 0, then all
666 // allocations for that type should be in the default range.
667 //
668 for (Type = (EFI_MEMORY_TYPE)0; Type < EfiMaxMemoryType; Type++) {
669 for (Index = 0; gMemoryTypeInformation[Index].Type != EfiMaxMemoryType; Index++) {
670 if (Type == (EFI_MEMORY_TYPE)gMemoryTypeInformation[Index].Type) {
671 mMemoryTypeStatistics[Type].InformationIndex = Index;
672 }
673 }
674
675 mMemoryTypeStatistics[Type].CurrentNumberOfPages = 0;
676 if (mMemoryTypeStatistics[Type].MaximumAddress == MAX_ALLOC_ADDRESS) {
677 mMemoryTypeStatistics[Type].MaximumAddress = mDefaultMaximumAddress;
678 }
679 }
680
681 mMemoryTypeInformationInitialized = TRUE;
682}
683
699VOID
701 IN EFI_MEMORY_TYPE Type,
703 IN UINT64 NumberOfPages,
704 IN UINT64 Attribute
705 )
706{
708 EFI_STATUS Status;
709 UINTN Index;
710 UINTN FreeIndex;
711 UINT64 Alignment;
712 UINT64 BinSize;
713
714 if ((Start & EFI_PAGE_MASK) != 0) {
715 return;
716 }
717
718 if ((Type >= EfiMaxMemoryType) && (Type < MEMORY_TYPE_OEM_RESERVED_MIN)) {
719 return;
720 }
721
723 End = Start + LShiftU64 (NumberOfPages, EFI_PAGE_SHIFT) - 1;
724 CoreAddRange (Type, Start, End, Attribute);
727
729 EfiMaxMemoryType,
730 Type,
731 Start,
732 LShiftU64 (NumberOfPages, EFI_PAGE_SHIFT)
733 );
734
735 //
736 // If Loading Module At Fixed Address feature is enabled. try to allocate memory with Runtime code & Boot time code type
737 //
738 if (PcdGet64 (PcdLoadModuleAtFixAddressEnable) != 0) {
740 }
741
742 //
743 // Check to see if the statistics for the different memory types have already been established
744 //
745 if (mMemoryTypeInformationInitialized) {
746 return;
747 }
748
749 //
750 // Loop through each memory type in the order specified by the gMemoryTypeInformation[] array
751 //
752 for (Index = 0; gMemoryTypeInformation[Index].Type != EfiMaxMemoryType; Index++) {
753 //
754 // Make sure the memory type in the gMemoryTypeInformation[] array is valid
755 //
756 Type = (EFI_MEMORY_TYPE)(gMemoryTypeInformation[Index].Type);
757 if ((UINT32)Type > EfiMaxMemoryType) {
758 continue;
759 }
760
761 if (gMemoryTypeInformation[Index].NumberOfPages != 0) {
763 if ((gMemoryTypeInformation[Index].Type == EfiReservedMemoryType) ||
764 (gMemoryTypeInformation[Index].Type == EfiACPIMemoryNVS) ||
765 (gMemoryTypeInformation[Index].Type == EfiRuntimeServicesCode) ||
766 (gMemoryTypeInformation[Index].Type == EfiRuntimeServicesData))
767 {
768 Alignment = RUNTIME_PAGE_ALLOCATION_GRANULARITY;
769 }
770
771 BinSize = EFI_PAGES_TO_SIZE ((UINTN)gMemoryTypeInformation[Index].NumberOfPages);
772 BinSize = ALIGN_VALUE (BinSize, Alignment);
773
774 gMemoryTypeInformation[Index].NumberOfPages = (UINT32)EFI_SIZE_TO_PAGES ((UINTN)BinSize);
775
776 //
777 // Allocate pages for the current memory type from the top of available memory
778 //
779 Status = CoreAllocatePages (
781 Type,
782 gMemoryTypeInformation[Index].NumberOfPages,
783 &mMemoryTypeStatistics[Type].BaseAddress
784 );
785 if (EFI_ERROR (Status)) {
786 //
787 // If an error occurs allocating the pages for the current memory type, then
788 // free all the pages allocates for the previous memory types and return. This
789 // operation with be retied when/if more memory is added to the system
790 //
791 for (FreeIndex = 0; FreeIndex < Index; FreeIndex++) {
792 //
793 // Make sure the memory type in the gMemoryTypeInformation[] array is valid
794 //
795 Type = (EFI_MEMORY_TYPE)(gMemoryTypeInformation[FreeIndex].Type);
796 if ((UINT32)Type > EfiMaxMemoryType) {
797 continue;
798 }
799
800 if (gMemoryTypeInformation[FreeIndex].NumberOfPages != 0) {
802 mMemoryTypeStatistics[Type].BaseAddress,
803 gMemoryTypeInformation[FreeIndex].NumberOfPages
804 );
805 mMemoryTypeStatistics[Type].BaseAddress = 0;
806 mMemoryTypeStatistics[Type].MaximumAddress = MAX_ALLOC_ADDRESS;
807 }
808 }
809
810 return;
811 }
812
813 //
814 // Compute the address at the top of the current statistics
815 //
816 mMemoryTypeStatistics[Type].MaximumAddress =
817 mMemoryTypeStatistics[Type].BaseAddress +
818 LShiftU64 (gMemoryTypeInformation[Index].NumberOfPages, EFI_PAGE_SHIFT) - 1;
819
820 //
821 // If the current base address is the lowest address so far, then update the default
822 // maximum address
823 //
824 if (mMemoryTypeStatistics[Type].BaseAddress < mDefaultMaximumAddress) {
825 mDefaultMaximumAddress = mMemoryTypeStatistics[Type].BaseAddress - 1;
826 }
827 }
828 }
829
830 //
831 // There was enough system memory for all the the memory types were allocated. So,
832 // those memory areas can be freed for future allocations, and all future memory
833 // allocations can occur within their respective bins
834 //
835 for (Index = 0; gMemoryTypeInformation[Index].Type != EfiMaxMemoryType; Index++) {
836 //
837 // Make sure the memory type in the gMemoryTypeInformation[] array is valid
838 //
839 Type = (EFI_MEMORY_TYPE)(gMemoryTypeInformation[Index].Type);
840 if ((UINT32)Type > EfiMaxMemoryType) {
841 continue;
842 }
843
844 if (gMemoryTypeInformation[Index].NumberOfPages != 0) {
846 mMemoryTypeStatistics[Type].BaseAddress,
847 gMemoryTypeInformation[Index].NumberOfPages
848 );
849 mMemoryTypeStatistics[Type].NumberOfPages = gMemoryTypeInformation[Index].NumberOfPages;
850 gMemoryTypeInformation[Index].NumberOfPages = 0;
851 }
852 }
853
854 //
855 // If the number of pages reserved for a memory type is 0, then all allocations for that type
856 // should be in the default range.
857 //
858 for (Type = (EFI_MEMORY_TYPE)0; Type < EfiMaxMemoryType; Type++) {
859 for (Index = 0; gMemoryTypeInformation[Index].Type != EfiMaxMemoryType; Index++) {
860 if (Type == (EFI_MEMORY_TYPE)gMemoryTypeInformation[Index].Type) {
861 mMemoryTypeStatistics[Type].InformationIndex = Index;
862 }
863 }
864
865 mMemoryTypeStatistics[Type].CurrentNumberOfPages = 0;
866 if (mMemoryTypeStatistics[Type].MaximumAddress == MAX_ALLOC_ADDRESS) {
867 mMemoryTypeStatistics[Type].MaximumAddress = mDefaultMaximumAddress;
868 }
869 }
870
871 mMemoryTypeInformationInitialized = TRUE;
872}
873
896 IN UINT64 Start,
897 IN UINT64 NumberOfPages,
898 IN BOOLEAN ChangingType,
899 IN EFI_MEMORY_TYPE NewType,
900 IN BOOLEAN ChangingAttributes,
901 IN UINT64 NewAttributes
902 )
903{
904 UINT64 NumberOfBytes;
905 UINT64 End;
906 UINT64 RangeEnd;
907 UINT64 Attribute;
908 EFI_MEMORY_TYPE MemType;
909 LIST_ENTRY *Link;
910 MEMORY_MAP *Entry;
911
912 Entry = NULL;
913 NumberOfBytes = LShiftU64 (NumberOfPages, EFI_PAGE_SHIFT);
914 End = Start + NumberOfBytes - 1;
915
916 ASSERT (NumberOfPages);
917 ASSERT ((Start & EFI_PAGE_MASK) == 0);
918 ASSERT (End > Start);
919 ASSERT_LOCKED (&gMemoryLock);
920 ASSERT ((ChangingType == FALSE) || (ChangingAttributes == FALSE));
921
922 if ((NumberOfPages == 0) || ((Start & EFI_PAGE_MASK) != 0) || (Start >= End)) {
923 return EFI_INVALID_PARAMETER;
924 }
925
926 //
927 // Convert the entire range
928 //
929
930 while (Start < End) {
931 //
932 // Find the entry that the covers the range
933 //
934 for (Link = gMemoryMap.ForwardLink; Link != &gMemoryMap; Link = Link->ForwardLink) {
935 Entry = CR (Link, MEMORY_MAP, Link, MEMORY_MAP_SIGNATURE);
936
937 if ((Entry->Start <= Start) && (Entry->End > Start)) {
938 break;
939 }
940 }
941
942 if ((Link == &gMemoryMap) || (Entry == NULL)) {
943 DEBUG ((DEBUG_ERROR | DEBUG_PAGE, "ConvertPages: failed to find range %lx - %lx\n", Start, End));
944 return EFI_NOT_FOUND;
945 }
946
947 //
948 // If we are converting the type of the range from EfiConventionalMemory to
949 // another type, we have to ensure that the entire range is covered by a
950 // single entry.
951 //
952 if (ChangingType && (NewType != EfiConventionalMemory)) {
953 if (Entry->End < End) {
954 DEBUG ((DEBUG_ERROR | DEBUG_PAGE, "ConvertPages: range %lx - %lx covers multiple entries\n", Start, End));
955 return EFI_NOT_FOUND;
956 }
957 }
958
959 //
960 // Convert range to the end, or to the end of the descriptor
961 // if that's all we've got
962 //
963 RangeEnd = End;
964 if (Entry == NULL) {
965 ASSERT (Entry != NULL);
966 return EFI_NOT_FOUND;
967 }
968
969 if (Entry->End < End) {
970 RangeEnd = Entry->End;
971 }
972
973 if (ChangingType) {
974 DEBUG ((DEBUG_PAGE, "ConvertRange: %lx-%lx to type %d\n", Start, RangeEnd, NewType));
975 }
976
977 if (ChangingAttributes) {
978 DEBUG ((DEBUG_PAGE, "ConvertRange: %lx-%lx to attr %lx\n", Start, RangeEnd, NewAttributes));
979 }
980
981 if (ChangingType) {
982 //
983 // Debug code - verify conversion is allowed
984 //
985 if (!((NewType == EfiConventionalMemory) ? 1 : 0) ^ ((Entry->Type == EfiConventionalMemory) ? 1 : 0)) {
986 DEBUG ((DEBUG_ERROR | DEBUG_PAGE, "ConvertPages: Incompatible memory types, "));
987 if (Entry->Type == EfiConventionalMemory) {
988 DEBUG ((DEBUG_ERROR | DEBUG_PAGE, "the pages to free have been freed\n"));
989 } else {
990 DEBUG ((DEBUG_ERROR | DEBUG_PAGE, "the pages to allocate have been allocated\n"));
991 }
992
993 return EFI_NOT_FOUND;
994 }
995
996 //
997 // Update counters for the number of pages allocated to each memory type
998 //
999 if ((UINT32)Entry->Type < EfiMaxMemoryType) {
1000 if (((Start >= mMemoryTypeStatistics[Entry->Type].BaseAddress) && (Start <= mMemoryTypeStatistics[Entry->Type].MaximumAddress)) ||
1001 ((Start >= mDefaultBaseAddress) && (Start <= mDefaultMaximumAddress)))
1002 {
1003 if (NumberOfPages > mMemoryTypeStatistics[Entry->Type].CurrentNumberOfPages) {
1004 mMemoryTypeStatistics[Entry->Type].CurrentNumberOfPages = 0;
1005 } else {
1006 mMemoryTypeStatistics[Entry->Type].CurrentNumberOfPages -= NumberOfPages;
1007 }
1008 }
1009 }
1010
1011 if ((UINT32)NewType < EfiMaxMemoryType) {
1012 if (((Start >= mMemoryTypeStatistics[NewType].BaseAddress) && (Start <= mMemoryTypeStatistics[NewType].MaximumAddress)) ||
1013 ((Start >= mDefaultBaseAddress) && (Start <= mDefaultMaximumAddress)))
1014 {
1015 mMemoryTypeStatistics[NewType].CurrentNumberOfPages += NumberOfPages;
1016 if (mMemoryTypeStatistics[NewType].CurrentNumberOfPages > gMemoryTypeInformation[mMemoryTypeStatistics[NewType].InformationIndex].NumberOfPages) {
1017 gMemoryTypeInformation[mMemoryTypeStatistics[NewType].InformationIndex].NumberOfPages = (UINT32)mMemoryTypeStatistics[NewType].CurrentNumberOfPages;
1018 }
1019 }
1020 }
1021 }
1022
1023 //
1024 // Pull range out of descriptor
1025 //
1026 if (Entry->Start == Start) {
1027 //
1028 // Clip start
1029 //
1030 Entry->Start = RangeEnd + 1;
1031 } else if (Entry->End == RangeEnd) {
1032 //
1033 // Clip end
1034 //
1035 Entry->End = Start - 1;
1036 } else {
1037 //
1038 // Pull it out of the center, clip current
1039 //
1040
1041 //
1042 // Add a new one
1043 //
1044 mMapStack[mMapDepth].Signature = MEMORY_MAP_SIGNATURE;
1045 mMapStack[mMapDepth].FromPages = FALSE;
1046 mMapStack[mMapDepth].Type = Entry->Type;
1047 mMapStack[mMapDepth].Start = RangeEnd+1;
1048 mMapStack[mMapDepth].End = Entry->End;
1049
1050 //
1051 // Inherit Attribute from the Memory Descriptor that is being clipped
1052 //
1053 mMapStack[mMapDepth].Attribute = Entry->Attribute;
1054
1055 Entry->End = Start - 1;
1056 ASSERT (Entry->Start < Entry->End);
1057
1058 Entry = &mMapStack[mMapDepth];
1059 InsertTailList (&gMemoryMap, &Entry->Link);
1060
1061 mMapDepth += 1;
1062 ASSERT (mMapDepth < MAX_MAP_DEPTH);
1063 }
1064
1065 //
1066 // The new range inherits the same Attribute as the Entry
1067 // it is being cut out of unless attributes are being changed
1068 //
1069 if (ChangingType) {
1070 Attribute = Entry->Attribute;
1071 MemType = NewType;
1072 } else {
1073 Attribute = NewAttributes;
1074 MemType = Entry->Type;
1075 }
1076
1077 //
1078 // If the descriptor is empty, then remove it from the map
1079 //
1080 if (Entry->Start == Entry->End + 1) {
1081 RemoveMemoryMapEntry (Entry);
1082 Entry = NULL;
1083 }
1084
1085 //
1086 // Add our new range in. Don't do this for freed pages if freed-memory
1087 // guard is enabled.
1088 //
1089 if (!IsHeapGuardEnabled (GUARD_HEAP_TYPE_FREED) ||
1090 !ChangingType ||
1091 (MemType != EfiConventionalMemory))
1092 {
1093 CoreAddRange (MemType, Start, RangeEnd, Attribute);
1094 }
1095
1096 if (ChangingType && (MemType == EfiConventionalMemory)) {
1097 //
1098 // Avoid calling DEBUG_CLEAR_MEMORY() for an address of 0 because this
1099 // macro will ASSERT() if address is 0. Instead, CoreAddRange() guarantees
1100 // that the page starting at address 0 is always filled with zeros.
1101 //
1102 if (Start == 0) {
1103 if (RangeEnd > EFI_PAGE_SIZE) {
1104 DEBUG_CLEAR_MEMORY ((VOID *)(UINTN)EFI_PAGE_SIZE, (UINTN)(RangeEnd - EFI_PAGE_SIZE + 1));
1105 }
1106 } else {
1107 DEBUG_CLEAR_MEMORY ((VOID *)(UINTN)Start, (UINTN)(RangeEnd - Start + 1));
1108 }
1109 }
1110
1111 //
1112 // Move any map descriptor stack to general pool
1113 //
1115
1116 //
1117 // Bump the starting address, and convert the next range
1118 //
1119 Start = RangeEnd + 1;
1120 }
1121
1122 //
1123 // Converted the whole range, done
1124 //
1125
1126 return EFI_SUCCESS;
1127}
1128
1147 IN UINT64 Start,
1148 IN UINT64 NumberOfPages,
1149 IN EFI_MEMORY_TYPE NewType
1150 )
1151{
1152 return CoreConvertPagesEx (Start, NumberOfPages, TRUE, NewType, FALSE, 0);
1153}
1154
1164VOID
1167 IN UINT64 NumberOfPages,
1168 IN UINT64 NewAttributes
1169 )
1170{
1172
1173 //
1174 // Update the attributes to the new value
1175 //
1176 CoreConvertPagesEx (Start, NumberOfPages, FALSE, (EFI_MEMORY_TYPE)0, TRUE, NewAttributes);
1177
1179}
1180
1196UINT64
1198 IN UINT64 MaxAddress,
1199 IN UINT64 MinAddress,
1200 IN UINT64 NumberOfPages,
1201 IN EFI_MEMORY_TYPE NewType,
1202 IN UINTN Alignment,
1203 IN BOOLEAN NeedGuard
1204 )
1205{
1206 UINT64 NumberOfBytes;
1207 UINT64 Target;
1208 UINT64 DescStart;
1209 UINT64 DescEnd;
1210 UINT64 DescNumberOfBytes;
1211 LIST_ENTRY *Link;
1212 MEMORY_MAP *Entry;
1213
1214 if ((MaxAddress < EFI_PAGE_MASK) || (NumberOfPages == 0)) {
1215 return 0;
1216 }
1217
1218 if ((MaxAddress & EFI_PAGE_MASK) != EFI_PAGE_MASK) {
1219 //
1220 // If MaxAddress is not aligned to the end of a page
1221 //
1222
1223 //
1224 // Change MaxAddress to be 1 page lower
1225 //
1226 MaxAddress -= (EFI_PAGE_MASK + 1);
1227
1228 //
1229 // Set MaxAddress to a page boundary
1230 //
1231 MaxAddress &= ~(UINT64)EFI_PAGE_MASK;
1232
1233 //
1234 // Set MaxAddress to end of the page
1235 //
1236 MaxAddress |= EFI_PAGE_MASK;
1237 }
1238
1239 NumberOfBytes = LShiftU64 (NumberOfPages, EFI_PAGE_SHIFT);
1240 Target = 0;
1241
1242 for (Link = gMemoryMap.ForwardLink; Link != &gMemoryMap; Link = Link->ForwardLink) {
1243 Entry = CR (Link, MEMORY_MAP, Link, MEMORY_MAP_SIGNATURE);
1244
1245 //
1246 // If it's not a free entry, don't bother with it
1247 //
1248 if (Entry->Type != EfiConventionalMemory) {
1249 continue;
1250 }
1251
1252 //
1253 // Don't allocate out of Special-Purpose memory.
1254 //
1255 if ((Entry->Attribute & EFI_MEMORY_SP) != 0) {
1256 continue;
1257 }
1258
1259 DescStart = Entry->Start;
1260 DescEnd = Entry->End;
1261
1262 //
1263 // If desc is past max allowed address or below min allowed address, skip it
1264 //
1265 if ((DescStart >= MaxAddress) || (DescEnd < MinAddress)) {
1266 continue;
1267 }
1268
1269 //
1270 // If desc ends past max allowed address, clip the end
1271 //
1272 if (DescEnd >= MaxAddress) {
1273 DescEnd = MaxAddress;
1274 }
1275
1276 DescEnd = ((DescEnd + 1) & (~((UINT64)Alignment - 1))) - 1;
1277
1278 // Skip if DescEnd is less than DescStart after alignment clipping
1279 if (DescEnd < DescStart) {
1280 continue;
1281 }
1282
1283 //
1284 // Compute the number of bytes we can used from this
1285 // descriptor, and see it's enough to satisfy the request
1286 //
1287 DescNumberOfBytes = DescEnd - DescStart + 1;
1288
1289 if (DescNumberOfBytes >= NumberOfBytes) {
1290 //
1291 // If the start of the allocated range is below the min address allowed, skip it
1292 //
1293 if ((DescEnd - NumberOfBytes + 1) < MinAddress) {
1294 continue;
1295 }
1296
1297 //
1298 // If this is the best match so far remember it
1299 //
1300 if (DescEnd > Target) {
1301 if (NeedGuard) {
1302 DescEnd = AdjustMemoryS (
1303 DescEnd + 1 - DescNumberOfBytes,
1304 DescNumberOfBytes,
1305 NumberOfBytes
1306 );
1307 if (DescEnd == 0) {
1308 continue;
1309 }
1310 }
1311
1312 Target = DescEnd;
1313 }
1314 }
1315 }
1316
1317 //
1318 // If this is a grow down, adjust target to be the allocation base
1319 //
1320 Target -= NumberOfBytes - 1;
1321
1322 //
1323 // If we didn't find a match, return 0
1324 //
1325 if ((Target & EFI_PAGE_MASK) != 0) {
1326 return 0;
1327 }
1328
1329 return Target;
1330}
1331
1346UINT64
1348 IN UINT64 MaxAddress,
1349 IN UINT64 NoPages,
1350 IN EFI_MEMORY_TYPE NewType,
1351 IN UINTN Alignment,
1352 IN BOOLEAN NeedGuard
1353 )
1354{
1355 UINT64 Start;
1356
1357 //
1358 // Attempt to find free pages in the preferred bin based on the requested memory type
1359 //
1360 if (((UINT32)NewType < EfiMaxMemoryType) && (MaxAddress >= mMemoryTypeStatistics[NewType].MaximumAddress)) {
1361 Start = CoreFindFreePagesI (
1362 mMemoryTypeStatistics[NewType].MaximumAddress,
1363 mMemoryTypeStatistics[NewType].BaseAddress,
1364 NoPages,
1365 NewType,
1366 Alignment,
1367 NeedGuard
1368 );
1369 if (Start != 0) {
1370 return Start;
1371 }
1372 }
1373
1374 //
1375 // Attempt to find free pages in the default allocation bin
1376 //
1377 if (MaxAddress >= mDefaultMaximumAddress) {
1378 Start = CoreFindFreePagesI (
1379 mDefaultMaximumAddress,
1380 0,
1381 NoPages,
1382 NewType,
1383 Alignment,
1384 NeedGuard
1385 );
1386 if (Start != 0) {
1387 if (Start < mDefaultBaseAddress) {
1388 mDefaultBaseAddress = NeedGuard ? Start - EFI_PAGE_SIZE : Start;
1389 }
1390
1391 return Start;
1392 }
1393 }
1394
1395 //
1396 // The allocation did not succeed in any of the prefered bins even after
1397 // promoting resources. Attempt to find free pages anywhere is the requested
1398 // address range. If this allocation fails, then there are not enough
1399 // resources anywhere to satisfy the request.
1400 //
1401 Start = CoreFindFreePagesI (
1402 MaxAddress,
1403 0,
1404 NoPages,
1405 NewType,
1406 Alignment,
1407 NeedGuard
1408 );
1409 if (Start != 0) {
1410 return Start;
1411 }
1412
1413 //
1414 // If allocations from the preferred bins fail, then attempt to promote memory resources.
1415 //
1416 if (!PromoteMemoryResource ()) {
1417 return 0;
1418 }
1419
1420 //
1421 // If any memory resources were promoted, then re-attempt the allocation
1422 //
1423 return FindFreePages (MaxAddress, NoPages, NewType, Alignment, NeedGuard);
1424}
1425
1446EFIAPI
1448 IN EFI_ALLOCATE_TYPE Type,
1449 IN EFI_MEMORY_TYPE MemoryType,
1450 IN UINTN NumberOfPages,
1451 IN OUT EFI_PHYSICAL_ADDRESS *Memory,
1452 IN BOOLEAN NeedGuard
1453 )
1454{
1455 EFI_STATUS Status;
1456 UINT64 Start;
1457 UINT64 NumberOfBytes;
1458 UINT64 End;
1459 UINT64 MaxAddress;
1460 UINTN Alignment;
1461 EFI_MEMORY_TYPE CheckType;
1462
1463 if ((UINT32)Type >= MaxAllocateType) {
1464 return EFI_INVALID_PARAMETER;
1465 }
1466
1467 if (((MemoryType >= EfiMaxMemoryType) && (MemoryType < MEMORY_TYPE_OEM_RESERVED_MIN)) ||
1468 (MemoryType == EfiConventionalMemory) || (MemoryType == EfiPersistentMemory) || (MemoryType == EfiUnacceptedMemoryType))
1469 {
1470 return EFI_INVALID_PARAMETER;
1471 }
1472
1473 if (Memory == NULL) {
1474 return EFI_INVALID_PARAMETER;
1475 }
1476
1478
1479 if ((MemoryType == EfiReservedMemoryType) ||
1480 (MemoryType == EfiACPIMemoryNVS) ||
1481 (MemoryType == EfiRuntimeServicesCode) ||
1482 (MemoryType == EfiRuntimeServicesData))
1483 {
1484 Alignment = RUNTIME_PAGE_ALLOCATION_GRANULARITY;
1485 }
1486
1487 //
1488 // The heap guard system does not support non-EFI_PAGE_SIZE alignments.
1489 // Architectures that require larger RUNTIME_PAGE_ALLOCATION_GRANULARITY
1490 // will have the runtime memory regions unguarded. OSes do not
1491 // map guard pages anyway, so this is a minimal loss. Not guarding prevents
1492 // alignment mismatches
1493 //
1494 if (Alignment != EFI_PAGE_SIZE) {
1495 NeedGuard = FALSE;
1496 }
1497
1498 if (Type == AllocateAddress) {
1499 if ((*Memory & (Alignment - 1)) != 0) {
1500 return EFI_NOT_FOUND;
1501 }
1502 }
1503
1504 NumberOfPages += EFI_SIZE_TO_PAGES (Alignment) - 1;
1505 NumberOfPages &= ~(EFI_SIZE_TO_PAGES (Alignment) - 1);
1506
1507 //
1508 // If this is for below a particular address, then
1509 //
1510 Start = *Memory;
1511
1512 //
1513 // The max address is the max natively addressable address for the processor
1514 //
1515 MaxAddress = MAX_ALLOC_ADDRESS;
1516
1517 //
1518 // Check for Type AllocateAddress,
1519 // if NumberOfPages is 0 or
1520 // if (NumberOfPages << EFI_PAGE_SHIFT) is above MAX_ALLOC_ADDRESS or
1521 // if (Start + NumberOfBytes) rolls over 0 or
1522 // if Start is above MAX_ALLOC_ADDRESS or
1523 // if End is above MAX_ALLOC_ADDRESS,
1524 // if Start..End overlaps any tracked MemoryTypeStatistics range
1525 // return EFI_NOT_FOUND.
1526 //
1527 if (Type == AllocateAddress) {
1528 // Page 0 is not allowed to be allocated as it is reserved for null pointer detection
1529 if (Start == 0) {
1530 return EFI_NOT_FOUND;
1531 }
1532
1533 if ((NumberOfPages == 0) ||
1534 (NumberOfPages > RShiftU64 (MaxAddress, EFI_PAGE_SHIFT)))
1535 {
1536 return EFI_NOT_FOUND;
1537 }
1538
1539 NumberOfBytes = LShiftU64 (NumberOfPages, EFI_PAGE_SHIFT);
1540 End = Start + NumberOfBytes - 1;
1541
1542 if ((Start >= End) ||
1543 (Start > MaxAddress) ||
1544 (End > MaxAddress))
1545 {
1546 return EFI_NOT_FOUND;
1547 }
1548
1549 //
1550 // A driver is allowed to call AllocatePages using an AllocateAddress type. This type of
1551 // AllocatePage request the exact physical address if it is not used. The existing code
1552 // will allow this request even in 'special' pages. The problem with this is that the
1553 // reason to have 'special' pages for OS hibernate/resume is defeated as memory is
1554 // fragmented.
1555 //
1556
1557 for (CheckType = (EFI_MEMORY_TYPE)0; CheckType < EfiMaxMemoryType; CheckType++) {
1558 if ((MemoryType != CheckType) &&
1559 mMemoryTypeStatistics[CheckType].Special &&
1560 (mMemoryTypeStatistics[CheckType].NumberOfPages > 0))
1561 {
1562 if ((Start >= mMemoryTypeStatistics[CheckType].BaseAddress) &&
1563 (Start <= mMemoryTypeStatistics[CheckType].MaximumAddress))
1564 {
1565 return EFI_NOT_FOUND;
1566 }
1567
1568 if ((End >= mMemoryTypeStatistics[CheckType].BaseAddress) &&
1569 (End <= mMemoryTypeStatistics[CheckType].MaximumAddress))
1570 {
1571 return EFI_NOT_FOUND;
1572 }
1573
1574 if ((Start < mMemoryTypeStatistics[CheckType].BaseAddress) &&
1575 (End > mMemoryTypeStatistics[CheckType].MaximumAddress))
1576 {
1577 return EFI_NOT_FOUND;
1578 }
1579 }
1580 }
1581 }
1582
1583 if (Type == AllocateMaxAddress) {
1584 MaxAddress = Start;
1585 }
1586
1588
1589 //
1590 // If not a specific address, then find an address to allocate
1591 //
1592 if (Type != AllocateAddress) {
1593 Start = FindFreePages (
1594 MaxAddress,
1595 NumberOfPages,
1596 MemoryType,
1597 Alignment,
1598 NeedGuard
1599 );
1600 if (Start == 0) {
1601 Status = EFI_OUT_OF_RESOURCES;
1602 goto Done;
1603 }
1604 }
1605
1606 //
1607 // Convert pages from FreeMemory to the requested type
1608 //
1609 if (NeedGuard) {
1610 Status = CoreConvertPagesWithGuard (Start, NumberOfPages, MemoryType);
1611 } else {
1612 Status = CoreConvertPages (Start, NumberOfPages, MemoryType);
1613 }
1614
1615 if (EFI_ERROR (Status)) {
1616 //
1617 // If requested memory region is unavailable it may be untested memory
1618 // Attempt to promote memory resources, then re-attempt the allocation
1619 //
1620 if (PromoteMemoryResource ()) {
1621 if (NeedGuard) {
1622 Status = CoreConvertPagesWithGuard (Start, NumberOfPages, MemoryType);
1623 } else {
1624 Status = CoreConvertPages (Start, NumberOfPages, MemoryType);
1625 }
1626 }
1627 }
1628
1629Done:
1631
1632 if (!EFI_ERROR (Status)) {
1633 if (NeedGuard) {
1634 SetGuardForMemory (Start, NumberOfPages);
1635 }
1636
1637 *Memory = Start;
1638 }
1639
1640 return Status;
1641}
1642
1662EFIAPI
1664 IN EFI_ALLOCATE_TYPE Type,
1665 IN EFI_MEMORY_TYPE MemoryType,
1666 IN UINTN NumberOfPages,
1668 )
1669{
1670 EFI_STATUS Status;
1671 BOOLEAN NeedGuard;
1672
1673 NeedGuard = IsPageTypeToGuard (MemoryType, Type) && !mOnGuarding;
1674 Status = CoreInternalAllocatePages (
1675 Type,
1676 MemoryType,
1677 NumberOfPages,
1678 Memory,
1679 NeedGuard
1680 );
1681 if (!EFI_ERROR (Status)) {
1684 MemoryProfileActionAllocatePages,
1685 MemoryType,
1686 EFI_PAGES_TO_SIZE (NumberOfPages),
1687 (VOID *)(UINTN)*Memory,
1688 NULL
1689 );
1693 MemoryType,
1694 *Memory,
1695 EFI_PAGES_TO_SIZE (NumberOfPages)
1696 );
1697 }
1698
1699 return Status;
1700}
1701
1715EFIAPI
1717 IN EFI_PHYSICAL_ADDRESS Memory,
1718 IN UINTN NumberOfPages,
1719 OUT EFI_MEMORY_TYPE *MemoryType OPTIONAL
1720 )
1721{
1722 EFI_STATUS Status;
1723 LIST_ENTRY *Link;
1724 MEMORY_MAP *Entry;
1725 UINTN Alignment;
1726 BOOLEAN IsGuarded;
1727
1728 //
1729 // Free the range
1730 //
1732
1733 //
1734 // Find the entry that the covers the range
1735 //
1736 IsGuarded = FALSE;
1737 Entry = NULL;
1738 for (Link = gMemoryMap.ForwardLink; Link != &gMemoryMap; Link = Link->ForwardLink) {
1739 Entry = CR (Link, MEMORY_MAP, Link, MEMORY_MAP_SIGNATURE);
1740 if ((Entry->Start <= Memory) && (Entry->End > Memory)) {
1741 break;
1742 }
1743 }
1744
1745 if (Link == &gMemoryMap) {
1746 Status = EFI_NOT_FOUND;
1747 goto Done;
1748 }
1749
1750 if (Entry == NULL) {
1751 ASSERT (Entry != NULL);
1752 Status = EFI_NOT_FOUND;
1753 goto Done;
1754 }
1755
1757
1758 if ((Entry->Type == EfiReservedMemoryType) ||
1759 (Entry->Type == EfiACPIMemoryNVS) ||
1760 (Entry->Type == EfiRuntimeServicesCode) ||
1761 (Entry->Type == EfiRuntimeServicesData))
1762 {
1763 Alignment = RUNTIME_PAGE_ALLOCATION_GRANULARITY;
1764 }
1765
1766 if ((Memory & (Alignment - 1)) != 0) {
1767 Status = EFI_INVALID_PARAMETER;
1768 goto Done;
1769 }
1770
1771 NumberOfPages += EFI_SIZE_TO_PAGES (Alignment) - 1;
1772 NumberOfPages &= ~(EFI_SIZE_TO_PAGES (Alignment) - 1);
1773
1774 if (MemoryType != NULL) {
1775 *MemoryType = Entry->Type;
1776 }
1777
1778 IsGuarded = IsPageTypeToGuard (Entry->Type, AllocateAnyPages) &&
1779 IsMemoryGuarded (Memory);
1780 if (IsGuarded) {
1781 Status = CoreConvertPagesWithGuard (
1782 Memory,
1783 NumberOfPages,
1785 );
1786 } else {
1787 Status = CoreConvertPages (Memory, NumberOfPages, EfiConventionalMemory);
1788 }
1789
1790Done:
1792 return Status;
1793}
1794
1807EFIAPI
1809 IN EFI_PHYSICAL_ADDRESS Memory,
1810 IN UINTN NumberOfPages
1811 )
1812{
1813 EFI_STATUS Status;
1814 EFI_MEMORY_TYPE MemoryType;
1815 UINT64 Attributes;
1816
1817 // check if this memory is returned to the core as RW at a minimum. If the memory attribute protocol is not installed,
1818 // then we assume that the memory is RW by default and continue to free it.
1819 if (gMemoryAttributeProtocol != NULL) {
1820 Status = gMemoryAttributeProtocol->GetMemoryAttributes (
1821 gMemoryAttributeProtocol,
1822 Memory,
1823 EFI_PAGES_TO_SIZE (NumberOfPages),
1824 &Attributes
1825 );
1826
1827 // if we failed to get the attributes, or if the memory is read-only or read-protected,
1828 // then we leak the memory and return success. This is done because the UEFI spec does not specify whether pages
1829 // should be freed with any specific permission attributes. As such, there exist bootloaders in the wild that will
1830 // free memory that is marked RO, which can crash the core if DebugClearMemory is enabled or can be passed out to a
1831 // driver in the next AllocatePages() call, which can cause a crash later on. It is deemed lower risk to leak the
1832 // memory than to attempt to fix up the attributes as that requires syncing the GCD and the page table.
1833 if ((Status == EFI_NO_MAPPING) ||
1834 (!EFI_ERROR (Status) && ((Attributes & EFI_MEMORY_RO) || (Attributes & EFI_MEMORY_RP))))
1835 {
1836 DEBUG ((
1837 DEBUG_WARN,
1838 "%a: Memory %llx for %llx Pages failed to get attributes with status %r or it is read-only or read-protected. "
1839 "Attributes: %llx. Leaking memory!\n",
1840 __func__,
1841 Memory,
1842 NumberOfPages,
1843 Status,
1844 Attributes
1845 ));
1846 return EFI_SUCCESS;
1847 }
1848 }
1849
1850 Status = CoreInternalFreePages (Memory, NumberOfPages, &MemoryType);
1851 if (!EFI_ERROR (Status)) {
1852 GuardFreedPagesChecked (Memory, NumberOfPages);
1855 MemoryProfileActionFreePages,
1856 MemoryType,
1857 EFI_PAGES_TO_SIZE (NumberOfPages),
1858 (VOID *)(UINTN)Memory,
1859 NULL
1860 );
1863 MemoryType,
1865 Memory,
1866 EFI_PAGES_TO_SIZE (NumberOfPages)
1867 );
1868 }
1869
1870 return Status;
1871}
1872
1889 IN EFI_MEMORY_DESCRIPTOR *MemoryMap,
1890 IN EFI_MEMORY_DESCRIPTOR *MemoryMapDescriptor,
1891 IN UINTN DescriptorSize
1892 )
1893{
1894 //
1895 // Traverse the array of descriptors in MemoryMap
1896 //
1897 for ( ; MemoryMap != MemoryMapDescriptor; MemoryMap = NEXT_MEMORY_DESCRIPTOR (MemoryMap, DescriptorSize)) {
1898 //
1899 // Check to see if the Type fields are identical.
1900 //
1901 if (MemoryMap->Type != MemoryMapDescriptor->Type) {
1902 continue;
1903 }
1904
1905 //
1906 // Check to see if the Attribute fields are identical.
1907 //
1908 if (MemoryMap->Attribute != MemoryMapDescriptor->Attribute) {
1909 continue;
1910 }
1911
1912 //
1913 // Check to see if MemoryMapDescriptor is immediately above MemoryMap
1914 //
1915 if (MemoryMap->PhysicalStart + EFI_PAGES_TO_SIZE ((UINTN)MemoryMap->NumberOfPages) == MemoryMapDescriptor->PhysicalStart) {
1916 //
1917 // Merge MemoryMapDescriptor into MemoryMap
1918 //
1919 MemoryMap->NumberOfPages += MemoryMapDescriptor->NumberOfPages;
1920
1921 //
1922 // Return MemoryMapDescriptor as the next available slot int he MemoryMap array
1923 //
1924 return MemoryMapDescriptor;
1925 }
1926
1927 //
1928 // Check to see if MemoryMapDescriptor is immediately below MemoryMap
1929 //
1930 if (MemoryMap->PhysicalStart - EFI_PAGES_TO_SIZE ((UINTN)MemoryMapDescriptor->NumberOfPages) == MemoryMapDescriptor->PhysicalStart) {
1931 //
1932 // Merge MemoryMapDescriptor into MemoryMap
1933 //
1934 MemoryMap->PhysicalStart = MemoryMapDescriptor->PhysicalStart;
1935 MemoryMap->VirtualStart = MemoryMapDescriptor->VirtualStart;
1936 MemoryMap->NumberOfPages += MemoryMapDescriptor->NumberOfPages;
1937
1938 //
1939 // Return MemoryMapDescriptor as the next available slot int he MemoryMap array
1940 //
1941 return MemoryMapDescriptor;
1942 }
1943 }
1944
1945 //
1946 // MemoryMapDescrtiptor could not be merged with any descriptors in MemoryMap.
1947 //
1948 // Return the slot immediately after MemoryMapDescriptor as the next available
1949 // slot in the MemoryMap array
1950 //
1951 return NEXT_MEMORY_DESCRIPTOR (MemoryMapDescriptor, DescriptorSize);
1952}
1953
1964static
1965VOID
1966SetEfiMemoryDescriptorType (
1967 IN EFI_MEMORY_DESCRIPTOR *MemoryMap,
1968 IN EFI_MEMORY_TYPE Type
1969 )
1970{
1971 if (MemoryMap == NULL) {
1972 ASSERT (MemoryMap != NULL);
1973 return;
1974 }
1975
1976 MemoryMap->Type = Type;
1977 if (MemoryMap->Type >= EfiMaxMemoryType) {
1978 return;
1979 }
1980
1981 if (mMemoryTypeStatistics[MemoryMap->Type].Runtime) {
1982 MemoryMap->Attribute |= EFI_MEMORY_RUNTIME;
1983 } else {
1984 MemoryMap->Attribute &= ~EFI_MEMORY_RUNTIME;
1985 }
1986}
1987
2019EFIAPI
2021 IN OUT UINTN *MemoryMapSize,
2022 IN OUT EFI_MEMORY_DESCRIPTOR *MemoryMap,
2023 OUT UINTN *MapKey,
2024 OUT UINTN *DescriptorSize,
2025 OUT UINT32 *DescriptorVersion
2026 )
2027{
2028 EFI_STATUS Status;
2029 UINTN Size;
2030 UINTN BufferSize;
2031 UINTN NumberOfEntries;
2032 LIST_ENTRY *Link;
2033 MEMORY_MAP *Entry;
2034 EFI_GCD_MAP_ENTRY *GcdMapEntry;
2035 EFI_GCD_MAP_ENTRY MergeGcdMapEntry;
2036 EFI_MEMORY_TYPE Type;
2037 EFI_MEMORY_DESCRIPTOR *MemoryMapStart;
2038 EFI_MEMORY_DESCRIPTOR *MemoryMapEnd;
2039 UINT64 BinStart;
2040 UINT64 BinEnd;
2041 UINT64 EntryStart;
2042 UINT64 EntryEnd;
2043 BOOLEAN Modified;
2044
2045 //
2046 // Make sure the parameters are valid
2047 //
2048 if (MemoryMapSize == NULL) {
2049 return EFI_INVALID_PARAMETER;
2050 }
2051
2053
2054 //
2055 // Count the number of Reserved and runtime MMIO entries
2056 // And, count the number of Persistent entries.
2057 //
2058 NumberOfEntries = 0;
2059 for (Link = mGcdMemorySpaceMap.ForwardLink; Link != &mGcdMemorySpaceMap; Link = Link->ForwardLink) {
2060 GcdMapEntry = CR (Link, EFI_GCD_MAP_ENTRY, Link, EFI_GCD_MAP_SIGNATURE);
2061 if ((GcdMapEntry->GcdMemoryType == EfiGcdMemoryTypePersistent) ||
2062 (GcdMapEntry->GcdMemoryType == EfiGcdMemoryTypeReserved) ||
2063 (GcdMapEntry->GcdMemoryType == EfiGcdMemoryTypeUnaccepted) ||
2064 ((GcdMapEntry->GcdMemoryType == EfiGcdMemoryTypeMemoryMappedIo) &&
2065 ((GcdMapEntry->Attributes & EFI_MEMORY_RUNTIME) == EFI_MEMORY_RUNTIME)))
2066 {
2067 NumberOfEntries++;
2068 }
2069 }
2070
2071 Size = sizeof (EFI_MEMORY_DESCRIPTOR);
2072
2073 //
2074 // Make sure Size != sizeof(EFI_MEMORY_DESCRIPTOR). This will
2075 // prevent people from having pointer math bugs in their code.
2076 // now you have to use *DescriptorSize to make things work.
2077 //
2078 Size += sizeof (UINT64) - (Size % sizeof (UINT64));
2079
2080 if (DescriptorSize != NULL) {
2081 *DescriptorSize = Size;
2082 }
2083
2084 if (DescriptorVersion != NULL) {
2085 *DescriptorVersion = EFI_MEMORY_DESCRIPTOR_VERSION;
2086 }
2087
2089
2090 //
2091 // Compute the buffer size needed to fit the entire map
2092 //
2093 BufferSize = Size * NumberOfEntries;
2094 for (Link = gMemoryMap.ForwardLink; Link != &gMemoryMap; Link = Link->ForwardLink) {
2095 BufferSize += Size;
2096 }
2097
2098 //
2099 // Add extra entries for each non-zero sized special memory type bin that may
2100 // be split. Worst case is that a memory entry overlaps entire bin and
2101 // requires an extra entry below the bin and an extra entry above the bin.
2102 //
2103 for (Type = (EFI_MEMORY_TYPE)0; Type < EfiMaxMemoryType; Type++) {
2104 if (mMemoryTypeStatistics[Type].Special &&
2105 (mMemoryTypeStatistics[Type].NumberOfPages > 0))
2106 {
2107 BufferSize += 2 * Size;
2108 }
2109 }
2110
2111 if (*MemoryMapSize < BufferSize) {
2112 Status = EFI_BUFFER_TOO_SMALL;
2113 goto Done;
2114 }
2115
2116 if (MemoryMap == NULL) {
2117 Status = EFI_INVALID_PARAMETER;
2118 goto Done;
2119 }
2120
2121 //
2122 // Build the map
2123 //
2124 ZeroMem (MemoryMap, BufferSize);
2125 MemoryMapStart = MemoryMap;
2126 MemoryMapEnd = MemoryMapStart;
2127 for (Link = gMemoryMap.ForwardLink; Link != &gMemoryMap; Link = Link->ForwardLink) {
2128 Entry = CR (Link, MEMORY_MAP, Link, MEMORY_MAP_SIGNATURE);
2129 ASSERT (Entry->VirtualStart == 0);
2130 MemoryMapEnd->PhysicalStart = Entry->Start;
2131 MemoryMapEnd->VirtualStart = 0;
2132 MemoryMapEnd->NumberOfPages = EFI_SIZE_TO_PAGES ((UINTN)(Entry->End - Entry->Start + 1));
2133 MemoryMapEnd->Attribute = Entry->Attribute;
2134 SetEfiMemoryDescriptorType (MemoryMapEnd, Entry->Type);
2135 MemoryMapEnd = MergeMemoryMapDescriptor (MemoryMapStart, MemoryMapEnd, Size);
2136 if ((UINTN)((UINT8 *)MemoryMapEnd - (UINT8 *)MemoryMapStart) > *MemoryMapSize) {
2137 Status = EFI_BUFFER_TOO_SMALL;
2138 goto Done;
2139 }
2140 }
2141
2142 //
2143 // Loop through all memory bins and split memory entries of type
2144 // EfiConventionalMemory if the memory map entry overlaps the beginning or end
2145 // of a memory bin. Convert memory map entries of type EfiConventionalMemory
2146 // that are completely contained within a memory bin to the memory bin type.
2147 //
2148 for (Type = (EFI_MEMORY_TYPE)0; Type < EfiMaxMemoryType; Type++) {
2149 //
2150 // If memory bin is empty or not special, then no split or conversion is required
2151 //
2152 if (mMemoryTypeStatistics[Type].NumberOfPages == 0) {
2153 continue;
2154 }
2155
2156 if (!mMemoryTypeStatistics[Type].Special) {
2157 continue;
2158 }
2159
2160 BinStart = mMemoryTypeStatistics[Type].BaseAddress;
2161 BinEnd = mMemoryTypeStatistics[Type].MaximumAddress;
2162
2163 Modified = TRUE;
2164 while (Modified) {
2165 BufferSize = ((UINT8 *)MemoryMapEnd - (UINT8 *)MemoryMapStart);
2166 MergeMemoryMap (MemoryMapStart, &BufferSize, Size);
2167 MemoryMapEnd = (EFI_MEMORY_DESCRIPTOR *)((UINT8 *)MemoryMapStart + BufferSize);
2168
2169 Modified = FALSE;
2170 for (MemoryMap = MemoryMapStart; MemoryMap < MemoryMapEnd; MemoryMap = NEXT_MEMORY_DESCRIPTOR (MemoryMap, Size)) {
2171 //
2172 // If the memory map entry is not EfiConventionalMemory, then no split or conversion is required
2173 //
2174 if (MemoryMap->Type != EfiConventionalMemory) {
2175 continue;
2176 }
2177
2178 EntryStart = MemoryMap->PhysicalStart;
2179 EntryEnd = EntryStart + EFI_PAGES_TO_SIZE ((UINTN)MemoryMap->NumberOfPages) - 1;
2180
2181 //
2182 // If the memory map entry does not overlap the memory bin, then no
2183 // split or conversion is required
2184 //
2185 if ((EntryEnd < BinStart) || (EntryStart > BinEnd)) {
2186 continue;
2187 }
2188
2189 //
2190 // If the memory map entry is completely contained within the memory
2191 // bin, then no split is needed and only the type should be converted.
2192 //
2193 if ((EntryStart >= BinStart) && (EntryEnd <= BinEnd)) {
2194 SetEfiMemoryDescriptorType (MemoryMap, Type);
2195 //
2196 // Memory map was modified. Restart processing from the beginning.
2197 //
2198 Modified = TRUE;
2199 break;
2200 }
2201
2202 //
2203 // If the memory map entry starts below the memory bin start, then split
2204 // at the memory bin start.
2205 //
2206 if (EntryStart < BinStart) {
2207 //
2208 // Shrink original entry to end at the beginning of the bin and
2209 // keep the original EfiConventionalMemory type and PhysicalAddress
2210 //
2211 MemoryMap->NumberOfPages = EFI_SIZE_TO_PAGES ((UINTN)(BinStart - EntryStart));
2212
2213 //
2214 // Insert a new entry of type memory bin type for the part after the memory bin start
2215 // Copy the current memory map entry contents into the inserted entry
2216 //
2217 CopyMem (
2218 NEXT_MEMORY_DESCRIPTOR (MemoryMap, Size),
2219 MemoryMap,
2220 ((UINT8 *)MemoryMapEnd - (UINT8 *)MemoryMap)
2221 );
2222 MemoryMap = NEXT_MEMORY_DESCRIPTOR (MemoryMap, Size);
2223 MemoryMapEnd = NEXT_MEMORY_DESCRIPTOR (MemoryMapEnd, Size);
2224 if ((UINTN)((UINT8 *)MemoryMapEnd - (UINT8 *)MemoryMapStart) > *MemoryMapSize) {
2225 //
2226 // Unexpected condition since max expected size for worst case splits was
2227 // computed and returned.
2228 //
2229 Status = EFI_BUFFER_TOO_SMALL;
2230 goto Done;
2231 }
2232
2233 MemoryMap->PhysicalStart = BinStart;
2234 MemoryMap->NumberOfPages = EFI_SIZE_TO_PAGES ((UINTN)(EntryEnd - BinStart + 1));
2235 SetEfiMemoryDescriptorType (MemoryMap, Type);
2236
2237 if (EntryEnd > BinEnd) {
2238 //
2239 // Shrink new entry to only cover the memory bin
2240 //
2241 MemoryMap->NumberOfPages = EFI_SIZE_TO_PAGES ((UINTN)(BinEnd - BinStart + 1));
2242
2243 //
2244 // The new entry extends beyond the memory bin end.
2245 // Create a new entry of type EfiConventionalMemory.
2246 //
2247 CopyMem (
2248 NEXT_MEMORY_DESCRIPTOR (MemoryMap, Size),
2249 MemoryMap,
2250 ((UINT8 *)MemoryMapEnd - (UINT8 *)MemoryMap)
2251 );
2252 MemoryMap = NEXT_MEMORY_DESCRIPTOR (MemoryMap, Size);
2253 MemoryMapEnd = NEXT_MEMORY_DESCRIPTOR (MemoryMapEnd, Size);
2254 if ((UINTN)((UINT8 *)MemoryMapEnd - (UINT8 *)MemoryMapStart) > *MemoryMapSize) {
2255 //
2256 // Unexpected condition since max expected size for worst case splits was
2257 // computed and returned.
2258 //
2259 Status = EFI_BUFFER_TOO_SMALL;
2260 goto Done;
2261 }
2262
2263 MemoryMap->PhysicalStart = BinEnd + 1;
2264 MemoryMap->NumberOfPages = EFI_SIZE_TO_PAGES ((UINTN)(EntryEnd - BinEnd));
2265 SetEfiMemoryDescriptorType (MemoryMap, EfiConventionalMemory);
2266 }
2267
2268 //
2269 // Memory map was modified. Restart processing from the beginning
2270 //
2271 Modified = TRUE;
2272 break;
2273 }
2274
2275 //
2276 // If the memory map entry ends above the memory bin end, then split at the memory bin end
2277 //
2278 if (EntryEnd > BinEnd) {
2279 //
2280 // Shrink the original entry for part before the memory bin end
2281 //
2282 MemoryMap->PhysicalStart = EntryStart;
2283 MemoryMap->NumberOfPages = EFI_SIZE_TO_PAGES ((UINTN)(BinEnd - EntryStart + 1));
2284 SetEfiMemoryDescriptorType (MemoryMap, Type);
2285
2286 //
2287 // Create new entry for the part before the memory bin end
2288 // EntryStart is guaranteed to be >= BinStart here, so the entire
2289 // entry can be converted to the memory bin type
2290 //
2291 CopyMem (
2292 NEXT_MEMORY_DESCRIPTOR (MemoryMap, Size),
2293 MemoryMap,
2294 ((UINT8 *)MemoryMapEnd - (UINT8 *)MemoryMap)
2295 );
2296 MemoryMap = NEXT_MEMORY_DESCRIPTOR (MemoryMap, Size);
2297 MemoryMapEnd = NEXT_MEMORY_DESCRIPTOR (MemoryMapEnd, Size);
2298 if ((UINTN)((UINT8 *)MemoryMapEnd - (UINT8 *)MemoryMapStart) > *MemoryMapSize) {
2299 Status = EFI_BUFFER_TOO_SMALL;
2300 goto Done;
2301 }
2302
2303 MemoryMap->PhysicalStart = BinEnd + 1;
2304 MemoryMap->NumberOfPages = EFI_SIZE_TO_PAGES ((UINTN)(EntryEnd - BinEnd));
2305 SetEfiMemoryDescriptorType (MemoryMap, EfiConventionalMemory);
2306
2307 //
2308 // Memory map was modified, so restart processing from the beginning
2309 //
2310 Modified = TRUE;
2311 break;
2312 }
2313 }
2314 }
2315 }
2316
2317 MemoryMap = MemoryMapEnd;
2318
2319 ZeroMem (&MergeGcdMapEntry, sizeof (MergeGcdMapEntry));
2320 GcdMapEntry = NULL;
2321 for (Link = mGcdMemorySpaceMap.ForwardLink; ; Link = Link->ForwardLink) {
2322 if (Link != &mGcdMemorySpaceMap) {
2323 //
2324 // Merge adjacent same type and attribute GCD memory range
2325 //
2326 GcdMapEntry = CR (Link, EFI_GCD_MAP_ENTRY, Link, EFI_GCD_MAP_SIGNATURE);
2327
2328 if ((MergeGcdMapEntry.Capabilities == GcdMapEntry->Capabilities) &&
2329 (MergeGcdMapEntry.Attributes == GcdMapEntry->Attributes) &&
2330 (MergeGcdMapEntry.GcdMemoryType == GcdMapEntry->GcdMemoryType) &&
2331 (MergeGcdMapEntry.GcdIoType == GcdMapEntry->GcdIoType))
2332 {
2333 MergeGcdMapEntry.EndAddress = GcdMapEntry->EndAddress;
2334 continue;
2335 }
2336 }
2337
2338 if ((MergeGcdMapEntry.GcdMemoryType == EfiGcdMemoryTypeReserved) ||
2339 ((MergeGcdMapEntry.GcdMemoryType == EfiGcdMemoryTypeMemoryMappedIo) &&
2340 ((MergeGcdMapEntry.Attributes & EFI_MEMORY_RUNTIME) == EFI_MEMORY_RUNTIME)))
2341 {
2342 //
2343 // Page Align GCD range is required. When it is converted to EFI_MEMORY_DESCRIPTOR,
2344 // it will be recorded as page PhysicalStart and NumberOfPages.
2345 //
2346 ASSERT ((MergeGcdMapEntry.BaseAddress & EFI_PAGE_MASK) == 0);
2347 ASSERT (((MergeGcdMapEntry.EndAddress - MergeGcdMapEntry.BaseAddress + 1) & EFI_PAGE_MASK) == 0);
2348
2349 //
2350 // Create EFI_MEMORY_DESCRIPTOR for every Reserved and runtime MMIO GCD entries
2351 //
2352 MemoryMap->PhysicalStart = MergeGcdMapEntry.BaseAddress;
2353 MemoryMap->VirtualStart = 0;
2354 MemoryMap->NumberOfPages = RShiftU64 ((MergeGcdMapEntry.EndAddress - MergeGcdMapEntry.BaseAddress + 1), EFI_PAGE_SHIFT);
2355 MemoryMap->Attribute = (MergeGcdMapEntry.Attributes & ~EFI_MEMORY_PORT_IO) |
2356 (MergeGcdMapEntry.Capabilities & (EFI_CACHE_ATTRIBUTE_MASK | EFI_MEMORY_ATTRIBUTE_MASK));
2357
2358 if (MergeGcdMapEntry.GcdMemoryType == EfiGcdMemoryTypeReserved) {
2359 MemoryMap->Type = EfiReservedMemoryType;
2360 } else if (MergeGcdMapEntry.GcdMemoryType == EfiGcdMemoryTypeMemoryMappedIo) {
2361 if ((MergeGcdMapEntry.Attributes & EFI_MEMORY_PORT_IO) == EFI_MEMORY_PORT_IO) {
2362 MemoryMap->Type = EfiMemoryMappedIOPortSpace;
2363 } else {
2364 MemoryMap->Type = EfiMemoryMappedIO;
2365 }
2366 }
2367
2368 //
2369 // Check to see if the new Memory Map Descriptor can be merged with an
2370 // existing descriptor if they are adjacent and have the same attributes
2371 //
2372 MemoryMap = MergeMemoryMapDescriptor (MemoryMapStart, MemoryMap, Size);
2373 if ((UINTN)((UINT8 *)MemoryMap - (UINT8 *)MemoryMapStart) > *MemoryMapSize) {
2374 //
2375 // Unexpected condition since max expected size for worst case splits was
2376 // computed and returned.
2377 //
2378 Status = EFI_BUFFER_TOO_SMALL;
2379 goto Done;
2380 }
2381 }
2382
2383 if (MergeGcdMapEntry.GcdMemoryType == EfiGcdMemoryTypePersistent) {
2384 //
2385 // Page Align GCD range is required. When it is converted to EFI_MEMORY_DESCRIPTOR,
2386 // it will be recorded as page PhysicalStart and NumberOfPages.
2387 //
2388 ASSERT ((MergeGcdMapEntry.BaseAddress & EFI_PAGE_MASK) == 0);
2389 ASSERT (((MergeGcdMapEntry.EndAddress - MergeGcdMapEntry.BaseAddress + 1) & EFI_PAGE_MASK) == 0);
2390
2391 //
2392 // Create EFI_MEMORY_DESCRIPTOR for every Persistent GCD entries
2393 //
2394 MemoryMap->PhysicalStart = MergeGcdMapEntry.BaseAddress;
2395 MemoryMap->VirtualStart = 0;
2396 MemoryMap->NumberOfPages = RShiftU64 ((MergeGcdMapEntry.EndAddress - MergeGcdMapEntry.BaseAddress + 1), EFI_PAGE_SHIFT);
2397 MemoryMap->Attribute = MergeGcdMapEntry.Attributes | EFI_MEMORY_NV |
2398 (MergeGcdMapEntry.Capabilities & (EFI_CACHE_ATTRIBUTE_MASK | EFI_MEMORY_ATTRIBUTE_MASK));
2399 MemoryMap->Type = EfiPersistentMemory;
2400
2401 //
2402 // Check to see if the new Memory Map Descriptor can be merged with an
2403 // existing descriptor if they are adjacent and have the same attributes
2404 //
2405 MemoryMap = MergeMemoryMapDescriptor (MemoryMapStart, MemoryMap, Size);
2406 if ((UINTN)((UINT8 *)MemoryMap - (UINT8 *)MemoryMapStart) > *MemoryMapSize) {
2407 //
2408 // Unexpected condition since max expected size for worst case splits was
2409 // computed and returned.
2410 //
2411 Status = EFI_BUFFER_TOO_SMALL;
2412 goto Done;
2413 }
2414 }
2415
2416 if (MergeGcdMapEntry.GcdMemoryType == EfiGcdMemoryTypeUnaccepted) {
2417 //
2418 // Page Align GCD range is required. When it is converted to EFI_MEMORY_DESCRIPTOR,
2419 // it will be recorded as page PhysicalStart and NumberOfPages.
2420 //
2421 ASSERT ((MergeGcdMapEntry.BaseAddress & EFI_PAGE_MASK) == 0);
2422 ASSERT (((MergeGcdMapEntry.EndAddress - MergeGcdMapEntry.BaseAddress + 1) & EFI_PAGE_MASK) == 0);
2423
2424 //
2425 // Create EFI_MEMORY_DESCRIPTOR for every Unaccepted GCD entries
2426 //
2427 MemoryMap->PhysicalStart = MergeGcdMapEntry.BaseAddress;
2428 MemoryMap->VirtualStart = 0;
2429 MemoryMap->NumberOfPages = RShiftU64 ((MergeGcdMapEntry.EndAddress - MergeGcdMapEntry.BaseAddress + 1), EFI_PAGE_SHIFT);
2430 MemoryMap->Attribute = MergeGcdMapEntry.Attributes |
2431 (MergeGcdMapEntry.Capabilities & (EFI_MEMORY_RP | EFI_MEMORY_WP | EFI_MEMORY_XP | EFI_MEMORY_RO |
2432 EFI_MEMORY_UC | EFI_MEMORY_UCE | EFI_MEMORY_WC | EFI_MEMORY_WT | EFI_MEMORY_WB));
2433 MemoryMap->Type = EfiUnacceptedMemoryType;
2434
2435 //
2436 // Check to see if the new Memory Map Descriptor can be merged with an
2437 // existing descriptor if they are adjacent and have the same attributes
2438 //
2439 MemoryMap = MergeMemoryMapDescriptor (MemoryMapStart, MemoryMap, Size);
2440 if ((UINTN)((UINT8 *)MemoryMap - (UINT8 *)MemoryMapStart) > *MemoryMapSize) {
2441 //
2442 // Unexpected condition since max expected size for worst case splits was
2443 // computed and returned.
2444 //
2445 Status = EFI_BUFFER_TOO_SMALL;
2446 goto Done;
2447 }
2448 }
2449
2450 if (Link == &mGcdMemorySpaceMap) {
2451 //
2452 // break loop when arrive at head.
2453 //
2454 break;
2455 }
2456
2457 if (GcdMapEntry != NULL) {
2458 //
2459 // Copy new GCD map entry for the following GCD range merge
2460 //
2461 CopyMem (&MergeGcdMapEntry, GcdMapEntry, sizeof (MergeGcdMapEntry));
2462 }
2463 }
2464
2465 //
2466 // Compute the size of the buffer actually used after all memory map descriptor merge operations
2467 //
2468 BufferSize = ((UINT8 *)MemoryMap - (UINT8 *)MemoryMapStart);
2469
2470 //
2471 // Note: Some OSs will treat EFI_MEMORY_DESCRIPTOR.Attribute as really
2472 // set attributes and change memory paging attribute accordingly.
2473 // But current EFI_MEMORY_DESCRIPTOR.Attribute is assigned by
2474 // value from Capabilities in GCD memory map. This might cause
2475 // boot problems. Clearing all page-access permission related
2476 // capabilities can workaround it. Following code is supposed to
2477 // be removed once the usage of EFI_MEMORY_DESCRIPTOR.Attribute
2478 // is clarified in UEFI spec and adopted by both EDK-II Core and
2479 // all supported OSs.
2480 //
2481 MemoryMapEnd = MemoryMap;
2482 MemoryMap = MemoryMapStart;
2483 while (MemoryMap < MemoryMapEnd) {
2484 MemoryMap->Attribute &= ~(UINT64)EFI_MEMORY_ACCESS_MASK;
2485 MemoryMap = NEXT_MEMORY_DESCRIPTOR (MemoryMap, Size);
2486 }
2487
2488 MergeMemoryMap (MemoryMapStart, &BufferSize, Size);
2489 MemoryMapEnd = (EFI_MEMORY_DESCRIPTOR *)((UINT8 *)MemoryMapStart + BufferSize);
2490
2491 Status = EFI_SUCCESS;
2492
2493Done:
2494 //
2495 // Update the map key finally
2496 //
2497 if (MapKey != NULL) {
2498 *MapKey = mMemoryMapKey;
2499 }
2500
2502
2504
2505 *MemoryMapSize = BufferSize;
2506
2507 DEBUG_CODE (
2509 );
2510
2511 return Status;
2512}
2513
2526VOID *
2528 IN EFI_MEMORY_TYPE PoolType,
2529 IN UINTN NumberOfPages,
2530 IN UINTN Alignment,
2531 IN BOOLEAN NeedGuard
2532 )
2533{
2534 UINT64 Start;
2535
2536 //
2537 // Find the pages to convert
2538 //
2539 Start = FindFreePages (
2541 NumberOfPages,
2542 PoolType,
2543 Alignment,
2544 NeedGuard
2545 );
2546
2547 //
2548 // Convert it to boot services data
2549 //
2550 if (Start == 0) {
2551 DEBUG ((DEBUG_ERROR | DEBUG_PAGE, "AllocatePoolPages: failed to allocate %d pages\n", (UINT32)NumberOfPages));
2552 } else {
2553 if (NeedGuard) {
2554 CoreConvertPagesWithGuard (Start, NumberOfPages, PoolType);
2555 } else {
2556 CoreConvertPages (Start, NumberOfPages, PoolType);
2557 }
2558 }
2559
2560 return (VOID *)(UINTN)Start;
2561}
2562
2570VOID
2572 IN EFI_PHYSICAL_ADDRESS Memory,
2573 IN UINTN NumberOfPages
2574 )
2575{
2576 CoreConvertPages (Memory, NumberOfPages, EfiConventionalMemory);
2577}
2578
2592 IN UINTN MapKey
2593 )
2594{
2595 EFI_STATUS Status;
2596 LIST_ENTRY *Link;
2597 MEMORY_MAP *Entry;
2598
2599 Status = EFI_SUCCESS;
2600
2602
2603 if (MapKey == mMemoryMapKey) {
2604 //
2605 // Make sure the memory map is following all the construction rules
2606 // This is the last chance we will be able to display any messages on
2607 // the console devices.
2608 //
2609
2610 for (Link = gMemoryMap.ForwardLink; Link != &gMemoryMap; Link = Link->ForwardLink) {
2611 Entry = CR (Link, MEMORY_MAP, Link, MEMORY_MAP_SIGNATURE);
2612 if (Entry->Type < EfiMaxMemoryType) {
2613 if (mMemoryTypeStatistics[Entry->Type].Runtime) {
2614 ASSERT (Entry->Type != EfiACPIReclaimMemory);
2615 ASSERT (Entry->Type != EfiACPIMemoryNVS);
2616 if ((Entry->Start & (RUNTIME_PAGE_ALLOCATION_GRANULARITY - 1)) != 0) {
2617 DEBUG ((DEBUG_ERROR | DEBUG_PAGE, "ExitBootServices: A RUNTIME memory entry is not on a proper alignment.\n"));
2618 Status = EFI_INVALID_PARAMETER;
2619 goto Done;
2620 }
2621
2622 if (((Entry->End + 1) & (RUNTIME_PAGE_ALLOCATION_GRANULARITY - 1)) != 0) {
2623 DEBUG ((DEBUG_ERROR | DEBUG_PAGE, "ExitBootServices: A RUNTIME memory entry is not on a proper alignment.\n"));
2624 Status = EFI_INVALID_PARAMETER;
2625 goto Done;
2626 }
2627 }
2628 }
2629 }
2630
2631 //
2632 // The map key they gave us matches what we expect. Fall through and
2633 // return success. In an ideal world we would clear out all of
2634 // EfiBootServicesCode and EfiBootServicesData. However this function
2635 // is not the last one called by ExitBootServices(), so we have to
2636 // preserve the memory contents.
2637 //
2638 } else {
2639 Status = EFI_INVALID_PARAMETER;
2640 }
2641
2642Done:
2644
2645 return Status;
2646}
#define DEFAULT_PAGE_ALLOCATION_GRANULARITY
UINT64 UINTN
#define MAX_ALLOC_ADDRESS
BOOLEAN EFIAPI IsListEmpty(IN CONST LIST_ENTRY *ListHead)
Definition: LinkedList.c:403
LIST_ENTRY *EFIAPI RemoveEntryList(IN CONST LIST_ENTRY *Entry)
Definition: LinkedList.c:590
UINT64 EFIAPI RShiftU64(IN UINT64 Operand, IN UINTN Count)
Definition: RShiftU64.c:28
#define INITIALIZE_LIST_HEAD_VARIABLE(ListHead)
Definition: BaseLib.h:2884
UINT64 EFIAPI LShiftU64(IN UINT64 Operand, IN UINTN Count)
Definition: LShiftU64.c:28
LIST_ENTRY *EFIAPI InsertTailList(IN OUT LIST_ENTRY *ListHead, IN OUT LIST_ENTRY *Entry)
Definition: LinkedList.c:259
VOID *EFIAPI CopyMem(OUT VOID *DestinationBuffer, IN CONST VOID *SourceBuffer, IN UINTN Length)
VOID *EFIAPI SetMem(OUT VOID *Buffer, IN UINTN Length, IN UINT8 Value)
Definition: SetMemWrapper.c:38
VOID *EFIAPI ZeroMem(OUT VOID *Buffer, IN UINTN Length)
VOID SetGuardForMemory(IN EFI_PHYSICAL_ADDRESS Memory, IN UINTN NumberOfPages)
Definition: HeapGuard.c:690
VOID EFIAPI GuardFreedPagesChecked(IN EFI_PHYSICAL_ADDRESS BaseAddress, IN UINTN Pages)
Definition: HeapGuard.c:1350
VOID EFIAPI DumpGuardedMemoryBitmap(VOID)
Definition: HeapGuard.c:1659
BOOLEAN PromoteGuardedFreePages(OUT EFI_PHYSICAL_ADDRESS *StartAddress, OUT EFI_PHYSICAL_ADDRESS *EndAddress)
Definition: HeapGuard.c:1531
BOOLEAN IsHeapGuardEnabled(UINT8 GuardType)
Definition: HeapGuard.c:674
UINT64 AdjustMemoryS(IN UINT64 Start, IN UINT64 Size, IN UINT64 SizeRequested)
Definition: HeapGuard.c:825
BOOLEAN EFIAPI IsMemoryGuarded(IN EFI_PHYSICAL_ADDRESS Address)
Definition: HeapGuard.c:486
BOOLEAN IsPageTypeToGuard(IN EFI_MEMORY_TYPE MemoryType, IN EFI_ALLOCATE_TYPE AllocateType)
Definition: HeapGuard.c:658
EFI_STATUS CoreConvertPagesWithGuard(IN UINT64 Start, IN UINTN NumberOfPages, IN EFI_MEMORY_TYPE NewType)
Definition: HeapGuard.c:1079
EFI_STATUS EFIAPI CoreGetMemorySpaceDescriptor(IN EFI_PHYSICAL_ADDRESS BaseAddress, OUT EFI_GCD_MEMORY_SPACE_DESCRIPTOR *Descriptor)
Definition: Gcd.c:1647
VOID CoreAcquireGcdMemoryLock(VOID)
Definition: Gcd.c:288
VOID CoreAcquireLock(IN EFI_LOCK *Lock)
Definition: Library.c:59
VOID CoreReleaseLock(IN EFI_LOCK *Lock)
Definition: Library.c:80
VOID MergeMemoryMap(IN OUT EFI_MEMORY_DESCRIPTOR *MemoryMap, IN OUT UINTN *MemoryMapSize, IN UINTN DescriptorSize)
EFI_STATUS EFIAPI CoreUpdateProfile(IN EFI_PHYSICAL_ADDRESS CallerAddress, IN MEMORY_PROFILE_ACTION Action, IN EFI_MEMORY_TYPE MemoryType, IN UINTN Size, IN VOID *Buffer, IN CHAR8 *ActionString OPTIONAL)
VOID CoreNotifySignalList(IN EFI_GUID *EventGroup)
Definition: Event.c:246
EFI_STATUS EFIAPI ApplyMemoryProtectionPolicy(IN EFI_MEMORY_TYPE OldType, IN EFI_MEMORY_TYPE NewType, IN EFI_PHYSICAL_ADDRESS Memory, IN UINT64 Length)
VOID InstallMemoryAttributesTableOnMemoryAllocation(IN EFI_MEMORY_TYPE MemoryType)
VOID CoreReleaseGcdMemoryLock(VOID)
Definition: Gcd.c:300
VOID CoreFreeMemoryMapStack(VOID)
Definition: Page.c:314
VOID RemoveMemoryMapEntry(IN OUT MEMORY_MAP *Entry)
Definition: Page.c:129
BOOLEAN PromoteMemoryResource(VOID)
Definition: Page.c:392
VOID CoreLoadingFixedAddressHook(VOID)
Definition: Page.c:479
VOID CoreAddMemoryDescriptor(IN EFI_MEMORY_TYPE Type, IN EFI_PHYSICAL_ADDRESS Start, IN UINT64 NumberOfPages, IN UINT64 Attribute)
Definition: Page.c:700
EFI_STATUS EFIAPI CoreFreePages(IN EFI_PHYSICAL_ADDRESS Memory, IN UINTN NumberOfPages)
Definition: Page.c:1808
VOID CoreUpdateMemoryAttributes(IN EFI_PHYSICAL_ADDRESS Start, IN UINT64 NumberOfPages, IN UINT64 NewAttributes)
Definition: Page.c:1165
EFI_STATUS EFIAPI CoreInternalFreePages(IN EFI_PHYSICAL_ADDRESS Memory, IN UINTN NumberOfPages, OUT EFI_MEMORY_TYPE *MemoryType OPTIONAL)
Definition: Page.c:1716
UINT64 FindFreePages(IN UINT64 MaxAddress, IN UINT64 NoPages, IN EFI_MEMORY_TYPE NewType, IN UINTN Alignment, IN BOOLEAN NeedGuard)
Definition: Page.c:1347
EFI_STATUS EFIAPI CoreAllocatePages(IN EFI_ALLOCATE_TYPE Type, IN EFI_MEMORY_TYPE MemoryType, IN UINTN NumberOfPages, OUT EFI_PHYSICAL_ADDRESS *Memory)
Definition: Page.c:1663
EFI_STATUS CoreConvertPages(IN UINT64 Start, IN UINT64 NumberOfPages, IN EFI_MEMORY_TYPE NewType)
Definition: Page.c:1146
EFI_STATUS EFIAPI CoreGetMemoryMap(IN OUT UINTN *MemoryMapSize, IN OUT EFI_MEMORY_DESCRIPTOR *MemoryMap, OUT UINTN *MapKey, OUT UINTN *DescriptorSize, OUT UINT32 *DescriptorVersion)
Definition: Page.c:2020
VOID * CoreAllocatePoolPages(IN EFI_MEMORY_TYPE PoolType, IN UINTN NumberOfPages, IN UINTN Alignment, IN BOOLEAN NeedGuard)
Definition: Page.c:2527
UINTN mMapDepth
Definition: Page.c:37
LIST_ENTRY mFreeMemoryMapEntryList
Definition: Page.c:46
MEMORY_MAP * AllocateMemoryMapEntry(VOID)
Definition: Page.c:268
EFI_MEMORY_DESCRIPTOR * MergeMemoryMapDescriptor(IN EFI_MEMORY_DESCRIPTOR *MemoryMap, IN EFI_MEMORY_DESCRIPTOR *MemoryMapDescriptor, IN UINTN DescriptorSize)
Definition: Page.c:1888
VOID CoreReleaseMemoryLock(VOID)
Definition: Page.c:115
VOID CoreAcquireMemoryLock(VOID)
Definition: Page.c:103
EFI_STATUS CoreConvertPagesEx(IN UINT64 Start, IN UINT64 NumberOfPages, IN BOOLEAN ChangingType, IN EFI_MEMORY_TYPE NewType, IN BOOLEAN ChangingAttributes, IN UINT64 NewAttributes)
Definition: Page.c:895
VOID CoreSetMemoryTypeInformationRange(IN EFI_PHYSICAL_ADDRESS Start, IN UINT64 Length)
Definition: Page.c:552
UINT64 CoreFindFreePagesI(IN UINT64 MaxAddress, IN UINT64 MinAddress, IN UINT64 NumberOfPages, IN EFI_MEMORY_TYPE NewType, IN UINTN Alignment, IN BOOLEAN NeedGuard)
Definition: Page.c:1197
MEMORY_MAP mMapStack[MAX_MAP_DEPTH]
Definition: Page.c:41
EFI_STATUS EFIAPI CoreInternalAllocatePages(IN EFI_ALLOCATE_TYPE Type, IN EFI_MEMORY_TYPE MemoryType, IN UINTN NumberOfPages, IN OUT EFI_PHYSICAL_ADDRESS *Memory, IN BOOLEAN NeedGuard)
Definition: Page.c:1447
VOID CoreAddRange(IN EFI_MEMORY_TYPE Type, IN EFI_PHYSICAL_ADDRESS Start, IN EFI_PHYSICAL_ADDRESS End, IN UINT64 Attribute)
Definition: Page.c:157
VOID CoreFreePoolPages(IN EFI_PHYSICAL_ADDRESS Memory, IN UINTN NumberOfPages)
Definition: Page.c:2571
EFI_STATUS CoreTerminateMemoryMap(IN UINTN MapKey)
Definition: Page.c:2591
#define NULL
Definition: Base.h:319
#define RETURN_ADDRESS(L)
Definition: Base.h:1379
#define VOID
Definition: Base.h:269
#define ALIGN_VALUE(Value, Alignment)
Definition: Base.h:948
#define TRUE
Definition: Base.h:301
#define FALSE
Definition: Base.h:307
#define IN
Definition: Base.h:279
#define OUT
Definition: Base.h:284
#define GLOBAL_REMOVE_IF_UNREFERENCED
Definition: Base.h:48
#define DEBUG(Expression)
Definition: DebugLib.h:435
#define CR(Record, TYPE, Field, TestSignature)
Definition: DebugLib.h:660
#define DEBUG_CLEAR_MEMORY(Address, Length)
Definition: DebugLib.h:606
#define DEBUG_CODE(Expression)
Definition: DebugLib.h:591
#define PcdGet64(TokenName)
Definition: PcdLib.h:375
#define PcdGet8(TokenName)
Definition: PcdLib.h:336
#define PcdGet32(TokenName)
Definition: PcdLib.h:362
@ EfiGcdMemoryTypeReserved
Definition: PiDxeCis.h:32
@ EfiGcdMemoryTypePersistent
Definition: PiDxeCis.h:49
@ EfiGcdMemoryTypeMoreReliable
Definition: PiDxeCis.h:58
@ EfiGcdMemoryTypeUnaccepted
Definition: PiDxeCis.h:63
@ EfiGcdMemoryTypeSystemMemory
Definition: PiDxeCis.h:38
@ EfiGcdMemoryTypeMemoryMappedIo
Definition: PiDxeCis.h:44
UINT64 EFI_PHYSICAL_ADDRESS
Definition: UefiBaseType.h:50
#define EFI_PAGES_TO_SIZE(Pages)
Definition: UefiBaseType.h:213
RETURN_STATUS EFI_STATUS
Definition: UefiBaseType.h:29
#define EFI_SIZE_TO_PAGES(Size)
Definition: UefiBaseType.h:200
#define EFI_SUCCESS
Definition: UefiBaseType.h:112
#define ASSERT_LOCKED(LockParameter)
Definition: UefiLib.h:331
EFI_MEMORY_TYPE
@ EfiUnusableMemory
@ EfiBootServicesData
@ EfiPersistentMemory
@ EfiReservedMemoryType
@ EfiBootServicesCode
@ EfiConventionalMemory
@ EfiLoaderData
@ EfiACPIMemoryNVS
@ EfiMemoryMappedIOPortSpace
@ EfiACPIReclaimMemory
@ EfiLoaderCode
@ EfiMemoryMappedIO
@ EfiUnacceptedMemoryType
@ EfiPalCode
@ EfiRuntimeServicesCode
@ EfiRuntimeServicesData
#define EFI_MEMORY_DESCRIPTOR_VERSION
Definition: UefiSpec.h:148
EFI_ALLOCATE_TYPE
Definition: UefiSpec.h:29
@ AllocateMaxAddress
Definition: UefiSpec.h:38
@ AllocateAddress
Definition: UefiSpec.h:42
@ AllocateAnyPages
Definition: UefiSpec.h:33
@ MaxAllocateType
Definition: UefiSpec.h:46
EFI_PHYSICAL_ADDRESS DxeCodeTopAddress
The top address below which the Dxe runtime code and below which the Dxe runtime/boot code and PEI co...
EFI_VIRTUAL_ADDRESS VirtualStart
Definition: UefiSpec.h:171
EFI_PHYSICAL_ADDRESS PhysicalStart
Definition: UefiSpec.h:165
UINT32 NumberOfPages
The pages of this type memory.
UINT32 Type
EFI memory type defined in UEFI specification.