OpenCore  1.0.4
OpenCore Bootloader
Loading...
Searching...
No Matches
MemoryAlloc.c
Go to the documentation of this file.
1
15#include <Uefi.h>
16
17#include <Guid/MemoryAttributesTable.h>
18#include <Library/BaseMemoryLib.h>
19#include <Library/BaseOverflowLib.h>
20#include <Library/DebugLib.h>
21#include <Library/MemoryAllocationLib.h>
22#include <Library/OcMemoryLib.h>
23#include <Library/UefiBootServicesTableLib.h>
24#include <Library/UefiLib.h>
25
26EFI_STATUS
28 IN EFI_MEMORY_TYPE MemoryType,
29 IN UINTN Pages,
30 IN OUT EFI_PHYSICAL_ADDRESS *Memory,
31 IN EFI_GET_MEMORY_MAP GetMemoryMap OPTIONAL,
32 IN EFI_ALLOCATE_PAGES AllocatePages OPTIONAL,
33 IN CHECK_ALLOCATION_RANGE CheckRange OPTIONAL
34 )
35{
36 EFI_STATUS Status;
37 UINTN MemoryMapSize;
38 EFI_MEMORY_DESCRIPTOR *MemoryMap;
39 UINTN MapKey;
40 UINTN DescriptorSize;
41 UINT32 DescriptorVersion;
42 EFI_MEMORY_DESCRIPTOR *MemoryMapEnd;
43 EFI_MEMORY_DESCRIPTOR *Desc;
44
46 &MemoryMapSize,
47 &MemoryMap,
48 &MapKey,
49 &DescriptorSize,
50 &DescriptorVersion,
51 GetMemoryMap,
52 NULL
53 );
54
55 if (EFI_ERROR (Status)) {
56 return Status;
57 }
58
59 Status = EFI_NOT_FOUND;
60
61 MemoryMapEnd = NEXT_MEMORY_DESCRIPTOR (MemoryMap, MemoryMapSize);
62 Desc = PREV_MEMORY_DESCRIPTOR (MemoryMapEnd, DescriptorSize);
63
64 for ( ; Desc >= MemoryMap; Desc = PREV_MEMORY_DESCRIPTOR (Desc, DescriptorSize)) {
65 //
66 // We are looking for some free memory descriptor that contains enough
67 // space below the specified memory.
68 //
69 if ((Desc->Type == EfiConventionalMemory) && (Pages <= Desc->NumberOfPages) &&
70 (Desc->PhysicalStart + EFI_PAGES_TO_SIZE (Pages) <= *Memory))
71 {
72 //
73 // Free block found
74 //
75 if (Desc->PhysicalStart + EFI_PAGES_TO_SIZE (Desc->NumberOfPages) <= *Memory) {
76 //
77 // The whole block is under Memory: allocate from the top of the block
78 //
79 *Memory = Desc->PhysicalStart + EFI_PAGES_TO_SIZE (Desc->NumberOfPages - Pages);
80 } else {
81 //
82 // The block contains enough pages under Memory, but spans above it - allocate below Memory
83 //
84 *Memory = *Memory - EFI_PAGES_TO_SIZE (Pages);
85 }
86
87 //
88 // Ensure that the found block does not overlap with the restricted area.
89 //
90 if ((CheckRange != NULL) && CheckRange (*Memory, EFI_PAGES_TO_SIZE (Pages))) {
91 continue;
92 }
93
94 Status = (AllocatePages != NULL ? AllocatePages : gBS->AllocatePages)(
95 AllocateAddress,
96 MemoryType,
97 Pages,
98 Memory
99 );
100
101 break;
102 }
103 }
104
105 FreePool (MemoryMap);
106
107 return Status;
108}
109
110UINT64
112 IN UINTN MemoryMapSize,
113 IN EFI_MEMORY_DESCRIPTOR *MemoryMap,
114 IN UINTN DescriptorSize,
115 OUT UINTN *DescriptorCount OPTIONAL
116 )
117{
118 UINTN DescNum;
119 UINT64 PageNum;
120 UINTN NumEntries;
121 UINTN Index;
122 EFI_MEMORY_DESCRIPTOR *Desc;
123
124 DescNum = 0;
125 PageNum = 0;
126 NumEntries = MemoryMapSize / DescriptorSize;
127 Desc = MemoryMap;
128
129 for (Index = 0; Index < NumEntries; ++Index) {
130 if ( (Desc->Type != EfiReservedMemoryType)
131 && ((Desc->Attribute & EFI_MEMORY_RUNTIME) != 0))
132 {
133 ++DescNum;
134 PageNum += Desc->NumberOfPages;
135 }
136
137 Desc = NEXT_MEMORY_DESCRIPTOR (Desc, DescriptorSize);
138 }
139
140 if (DescriptorCount != NULL) {
141 *DescriptorCount = DescNum;
142 }
143
144 return PageNum;
145}
146
147UINTN
149 OUT UINTN *LowerMemory OPTIONAL
150 )
151{
152 UINTN MemoryMapSize;
153 UINTN DescriptorSize;
154 EFI_MEMORY_DESCRIPTOR *MemoryMap;
155 EFI_MEMORY_DESCRIPTOR *EntryWalker;
156 UINTN FreePages;
157
158 FreePages = 0;
159 if (LowerMemory != NULL) {
160 *LowerMemory = 0;
161 }
162
163 MemoryMap = OcGetCurrentMemoryMap (&MemoryMapSize, &DescriptorSize, NULL, NULL, NULL, FALSE);
164 if (MemoryMap == NULL) {
165 return 0;
166 }
167
168 for (
169 EntryWalker = MemoryMap;
170 (UINT8 *)EntryWalker < ((UINT8 *)MemoryMap + MemoryMapSize);
171 EntryWalker = NEXT_MEMORY_DESCRIPTOR (EntryWalker, DescriptorSize))
172 {
173 if (EntryWalker->Type != EfiConventionalMemory) {
174 continue;
175 }
176
177 //
178 // This cannot overflow even on 32-bit systems unless they have > 16 TB of RAM,
179 // just assert to ensure that we have valid MemoryMap.
180 //
181 ASSERT (EntryWalker->NumberOfPages <= MAX_UINTN);
182 ASSERT (MAX_UINTN - EntryWalker->NumberOfPages >= FreePages);
183 FreePages += (UINTN)EntryWalker->NumberOfPages;
184
185 if ((LowerMemory == NULL) || (EntryWalker->PhysicalStart >= BASE_4GB)) {
186 continue;
187 }
188
189 if (EntryWalker->PhysicalStart + EFI_PAGES_TO_SIZE (EntryWalker->NumberOfPages) > BASE_4GB) {
190 *LowerMemory += (UINTN)EFI_SIZE_TO_PAGES (BASE_4GB - EntryWalker->PhysicalStart);
191 } else {
192 *LowerMemory += (UINTN)EntryWalker->NumberOfPages;
193 }
194 }
195
196 FreePool (MemoryMap);
197
198 return FreePages;
199}
UINTN OcCountFreePages(OUT UINTN *LowerMemory OPTIONAL)
EFI_STATUS OcAllocatePagesFromTop(IN EFI_MEMORY_TYPE MemoryType, IN UINTN Pages, IN OUT EFI_PHYSICAL_ADDRESS *Memory, IN EFI_GET_MEMORY_MAP GetMemoryMap OPTIONAL, IN EFI_ALLOCATE_PAGES AllocatePages OPTIONAL, IN CHECK_ALLOCATION_RANGE CheckRange OPTIONAL)
Definition MemoryAlloc.c:27
UINT64 OcCountRuntimePages(IN UINTN MemoryMapSize, IN EFI_MEMORY_DESCRIPTOR *MemoryMap, IN UINTN DescriptorSize, OUT UINTN *DescriptorCount OPTIONAL)
EFI_BOOT_SERVICES * gBS
EFI_MEMORY_DESCRIPTOR * OcGetCurrentMemoryMap(OUT UINTN *MemoryMapSize, OUT UINTN *DescriptorSize, OUT UINTN *MapKey OPTIONAL, OUT UINT32 *DescriptorVersion OPTIONAL, OUT UINTN *OriginalMemoryMapSize OPTIONAL, IN BOOLEAN IncludeSplitSpace)
Definition MemoryMap.c:116
#define PREV_MEMORY_DESCRIPTOR(MemoryDescriptor, Size)
Definition OcMemoryLib.h:25
EFI_STATUS OcGetCurrentMemoryMapAlloc(OUT UINTN *MemoryMapSize, OUT EFI_MEMORY_DESCRIPTOR **MemoryMap, OUT UINTN *MapKey, OUT UINTN *DescriptorSize, OUT UINT32 *DescriptorVersion, IN EFI_GET_MEMORY_MAP GetMemoryMap OPTIONAL, IN OUT EFI_PHYSICAL_ADDRESS *TopMemory OPTIONAL)
Definition MemoryMap.c:201
BOOLEAN(* CHECK_ALLOCATION_RANGE)(IN EFI_PHYSICAL_ADDRESS Address, IN UINTN Size)
#define ASSERT(x)
Definition coder.h:55