ReactOS 0.4.16-dev-2104-gb84fa49
uefimem.c
Go to the documentation of this file.
1/*
2 * PROJECT: FreeLoader UEFI Support
3 * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
4 * PURPOSE: Memory Management Functions
5 * COPYRIGHT: Copyright 2022 Justin Miller <justinmiller100@gmail.com>
6 */
7
8/* INCLUDES ******************************************************************/
9
10#include <uefildr.h>
11
12#include <debug.h>
14
15#define NEXT_MEMORY_DESCRIPTOR(Descriptor, DescriptorSize) \
16 (EFI_MEMORY_DESCRIPTOR*)((char*)(Descriptor) + (DescriptorSize))
17#define EXIT_STACK_SIZE 0x1000
18#define UNUSED_MAX_DESCRIPTOR_COUNT 10000
19
23 _In_ ULONG MaxCount,
24 _In_ PFN_NUMBER BasePage,
25 _In_ PFN_NUMBER PageCount,
26 _In_ TYPE_OF_MEMORY MemoryType);
27
28/* GLOBALS *******************************************************************/
29
33
41
43
44/* FUNCTIONS *****************************************************************/
45
46static
47VOID
49 _Out_ UINTN* LocMapKey,
50 _Out_ UINTN* LocMapSize,
51 _Out_ UINTN* LocDescriptorSize,
52 _Out_ UINT32* LocDescriptorVersion)
53{
56 ULONG Count = 0;
57
60 LocMapKey,
61 LocDescriptorSize,
62 LocDescriptorVersion);
63
64 /* Reallocate and retrieve again the needed memory map size (since memory
65 * allocated by AllocatePool() counts in the map), until it's OK. */
66 while (Status != EFI_SUCCESS)
67 {
68 /* Reallocate the memory map buffer */
69 if (EfiMemoryMap)
71
72 /* If MapSize never reports the correct size after the first time, increment */
73 AllocationSize = *LocMapSize + (*LocDescriptorSize * Count);
75 (VOID**)&EfiMemoryMap);
78 LocMapKey,
79 LocDescriptorSize,
80 LocDescriptorVersion);
81 Count++;
82 }
83}
84
85static
86VOID
90 _In_ PFN_COUNT SizeInPages,
91 _In_ TYPE_OF_MEMORY MemoryType)
92{
93 ULONG_PTR BasePage, PageCount;
94
95 BasePage = BaseAddress / EFI_PAGE_SIZE;
96 PageCount = SizeInPages;
97
98 /* Add the memory descriptor */
101 BasePage,
102 PageCount,
103 MemoryType);
104}
105
106static
109{
110 switch (EfiMemoryType)
111 {
113 return LoaderReserve;
114 case EfiLoaderCode:
115 return LoaderLoadedProgram;
116 case EfiLoaderData:
117 return LoaderLoadedProgram;
127 return LoaderFree;
129 return LoaderBad;
132 case EfiACPIMemoryNVS:
133 return LoaderReserve;
135 return LoaderReserve;
137 return LoaderReserve;
138 default:
139 break;
140 }
141 return LoaderReserve;
142}
143
146{
147 EFI_LOADED_IMAGE_PROTOCOL *LoadedImage;
148 UINT32 DescriptorVersion;
149 SIZE_T FreeldrMemMapSize;
152 UINTN MapSize;
153 UINTN MapKey;
155
157 PFREELDR_MEMORY_DESCRIPTOR FreeldrMem = NULL;
158 EFI_MEMORY_DESCRIPTOR* MapEntry = NULL;
159 UINT32 EntryCount = 0;
161
164 (VOID**)&LoadedImage);
165 if (Status != EFI_SUCCESS)
166 {
167 TRACE("Failed to find LoadedImageHandle with status: %d\n", Status);
168 UiMessageBoxCritical("Unable to initialize memory manager.");
169 return NULL;
170 }
171 OsLoaderBase = LoadedImage->ImageBase;
172 OsLoaderSize = LoadedImage->ImageSize;
173 PublicBootHandle = LoadedImage->DeviceHandle;
175
176 TRACE("UefiMemGetMemoryMap: Gather memory map\n");
177 PUEFI_LoadMemoryMap(&MapKey,
178 &MapSize,
180 &DescriptorVersion);
181
182 TRACE("Value of MapKey: %d\n", MapKey);
183 TRACE("Value of MapSize: %d\n", MapSize);
184 TRACE("Value of DescriptorSize: %d\n", DescriptorSize);
185 TRACE("Value of DescriptorVersion: %d\n", DescriptorVersion);
186
187 EntryCount = (MapSize / DescriptorSize);
188
189 FreeldrMemMapSize = (sizeof(FREELDR_MEMORY_DESCRIPTOR) * EntryCount);
191 FreeldrMemMapSize,
192 (void**)&FreeldrMem);
193 if (Status != EFI_SUCCESS)
194 {
195 TRACE("Failed to allocate pool with status %d\n", Status);
196 UiMessageBoxCritical("Unable to initialize memory manager.");
197 return NULL;
198 }
199
200 RtlZeroMemory(FreeldrMem, FreeldrMemMapSize);
201 MapEntry = EfiMemoryMap;
202 for (Index = 0; Index < EntryCount; ++Index)
203 {
204 TYPE_OF_MEMORY MemoryType = UefiConvertToFreeldrDesc(MapEntry->Type);
205 if (MemoryType == LoaderFree)
206 {
209 MapEntry->NumberOfPages,
210 &MapEntry->PhysicalStart);
211 if (Status != EFI_SUCCESS)
212 {
213 /* We failed to reserve the page, so change its type */
214 MemoryType = LoaderFirmwareTemporary;
215 }
216 }
217
218 /* Sometimes our loader can be loaded into higher memory than we ever allocate */
219 if (MemoryType == LoaderLoadedProgram)
220 {
221 if (((MapEntry->PhysicalStart + (MapEntry->NumberOfPages * PAGE_SIZE)) >> EFI_PAGE_SHIFT) > LoaderPagesSpanned)
222 {
223 /* This value needs to be adjusted if this occurs */
224 LoaderPagesSpanned = ((MapEntry->PhysicalStart + (MapEntry->NumberOfPages * PAGE_SIZE)) >> EFI_PAGE_SHIFT);
225 }
226 }
227
228 /* We really don't want to touch these reserved spots at all */
229 if (MemoryType != LoaderReserve)
230 {
231 UefiSetMemory(FreeldrMem,
232 MapEntry->PhysicalStart,
233 MapEntry->NumberOfPages,
234 MemoryType);
235 }
236
237 MapEntry = NEXT_MEMORY_DESCRIPTOR(MapEntry, DescriptorSize);
238 }
239
240 /* Windows expects the first page to be reserved, otherwise it asserts.
241 * However it can be just a free page on some UEFI systems. */
242 UefiSetMemory(FreeldrMem, 0x000000, 1, LoaderFirmwarePermanent);
243 *MemoryMapSize = FreeldrDescCount;
244 return FreeldrMem;
245}
246
247VOID
249{
250 UINTN MapKey;
251 UINTN MapSize;
254 UINT32 DescriptorVersion;
255
256 TRACE("Attempting to exit bootsevices\n");
257 PUEFI_LoadMemoryMap(&MapKey,
258 &MapSize,
260 &DescriptorVersion);
261
263 /* UEFI spec demands twice! */
264 if (Status != EFI_SUCCESS)
266
267 if (Status != EFI_SUCCESS)
268 {
269 TRACE("Failed to exit boot services with status: %d\n", Status);
270 FrLdrBugCheckWithMessage(EXIT_BOOTSERVICES_FAILURE,
271 __FILE__,
272 __LINE__,
273 "Failed to exit boot services with status: %d",
274 Status);
275 }
276 else
277 {
278 TRACE("Exited bootservices\n");
279 }
280}
281
282VOID
284{
285 _exituefi();
286}
#define WARNING
Definition: BusLogic958.h:56
#define EFI_LOADED_IMAGE_PROTOCOL_GUID
Definition: LoadedImage.h:21
ULONG_PTR PFN_NUMBER
UINT32 UINTN
unsigned int UINT32
#define EFI_PAGE_SIZE
Definition: UefiBaseType.h:189
RETURN_STATUS EFI_STATUS
Definition: UefiBaseType.h:31
#define EFI_PAGE_SHIFT
Definition: UefiBaseType.h:191
#define EFI_SUCCESS
Definition: UefiBaseType.h:120
EFI_MEMORY_TYPE
@ EfiUnusableMemory
@ EfiBootServicesData
@ EfiReservedMemoryType
@ EfiBootServicesCode
@ EfiConventionalMemory
@ EfiLoaderData
@ EfiACPIMemoryNVS
@ EfiMemoryMappedIOPortSpace
@ EfiACPIReclaimMemory
@ EfiLoaderCode
@ EfiMemoryMappedIO
@ EfiRuntimeServicesCode
@ EfiRuntimeServicesData
@ AllocateAddress
Definition: UefiSpec.h:45
EFI_GUID EfiLoadedImageProtocol
Definition: firmware.c:30
BIOS_MEMORY_MAP MemoryMap[32]
Definition: loader.c:11
DECLSPEC_NORETURN VOID FrLdrBugCheckWithMessage(ULONG BugCode, PCHAR File, ULONG Line, PSTR Format,...)
Definition: debug.c:29
#define DBG_DEFAULT_CHANNEL(ch)
Definition: debug.h:106
struct _FREELDR_MEMORY_DESCRIPTOR FREELDR_MEMORY_DESCRIPTOR
VOID UiMessageBoxCritical(_In_ PCSTR MessageText)
Definition: ui.c:372
#define NULL
Definition: types.h:112
#define PAGE_SIZE
Definition: env_spec_w32.h:49
IN PFCB IN PFILE_OBJECT FileObject IN ULONG AllocationSize
Definition: fatprocs.h:323
Status
Definition: gdiplustypes.h:25
_In_ HANDLE _Outptr_result_bytebuffer_ ViewSize PVOID * BaseAddress
Definition: mmfuncs.h:404
#define _Inout_
Definition: no_sal2.h:162
#define _Out_
Definition: no_sal2.h:160
#define _In_
Definition: no_sal2.h:158
int Count
Definition: noreturn.cpp:7
@ LoaderBad
Definition: arc.h:296
@ LoaderReserve
Definition: arc.h:317
@ LoaderFree
Definition: arc.h:295
@ LoaderFirmwareTemporary
Definition: arc.h:298
@ LoaderLoadedProgram
Definition: arc.h:297
@ LoaderFirmwarePermanent
Definition: arc.h:299
enum _TYPE_OF_MEMORY TYPE_OF_MEMORY
#define TRACE(s)
Definition: solgame.cpp:4
EFI_ALLOCATE_PAGES AllocatePages
Definition: UefiSpec.h:1810
EFI_FREE_POOL FreePool
Definition: UefiSpec.h:1814
EFI_HANDLE_PROTOCOL HandleProtocol
Definition: UefiSpec.h:1832
EFI_EXIT_BOOT_SERVICES ExitBootServices
Definition: UefiSpec.h:1846
EFI_ALLOCATE_POOL AllocatePool
Definition: UefiSpec.h:1813
EFI_GET_MEMORY_MAP GetMemoryMap
Definition: UefiSpec.h:1812
EFI_HANDLE DeviceHandle
The device handle that the EFI Image was loaded from.
Definition: LoadedImage.h:59
UINT64 ImageSize
The size in bytes of the loaded image.
Definition: LoadedImage.h:74
VOID * ImageBase
The base address at which the image was loaded.
Definition: LoadedImage.h:73
EFI_PHYSICAL_ADDRESS PhysicalStart
Definition: UefiSpec.h:99
EFI_BOOT_SERVICES * BootServices
Definition: UefiSpec.h:1959
_In_ SIZE_T DescriptorSize
Definition: nls.c:40
ULONG_PTR SIZE_T
Definition: typedefs.h:80
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
uint32_t ULONG_PTR
Definition: typedefs.h:65
uint32_t ULONG
Definition: typedefs.h:59
UINT32 FreeldrDescCount
Definition: uefimem.c:35
VOID UefiExitBootServices(VOID)
Definition: uefimem.c:248
EFI_MEMORY_DESCRIPTOR * EfiMemoryMap
Definition: uefimem.c:34
PVOID EndofExitStack
Definition: uefimem.c:40
static VOID PUEFI_LoadMemoryMap(_Out_ UINTN *LocMapKey, _Out_ UINTN *LocMapSize, _Out_ UINTN *LocDescriptorSize, _Out_ UINT32 *LocDescriptorVersion)
Definition: uefimem.c:48
ULONG AddMemoryDescriptor(_Inout_ PFREELDR_MEMORY_DESCRIPTOR List, _In_ ULONG MaxCount, _In_ PFN_NUMBER BasePage, _In_ PFN_NUMBER PageCount, _In_ TYPE_OF_MEMORY MemoryType)
EFI_HANDLE PublicBootHandle
Definition: uefimem.c:38
EFI_SYSTEM_TABLE * GlobalSystemTable
Definition: uefildr.c:16
static TYPE_OF_MEMORY UefiConvertToFreeldrDesc(EFI_MEMORY_TYPE EfiMemoryType)
Definition: uefimem.c:108
PVOID ExitStack
Definition: uefimem.c:39
PFREELDR_MEMORY_DESCRIPTOR UefiMemGetMemoryMap(ULONG *MemoryMapSize)
Definition: uefimem.c:145
PVOID OsLoaderBase
Definition: uefimem.c:36
static VOID UefiSetMemory(_Inout_ PFREELDR_MEMORY_DESCRIPTOR MemoryMap, _In_ ULONG_PTR BaseAddress, _In_ PFN_COUNT SizeInPages, _In_ TYPE_OF_MEMORY MemoryType)
Definition: uefimem.c:87
EFI_HANDLE GlobalImageHandle
Definition: uefildr.c:15
SIZE_T OsLoaderSize
Definition: uefimem.c:37
ULONG LoaderPagesSpanned
Definition: mm.c:29
#define UNUSED_MAX_DESCRIPTOR_COUNT
Definition: uefimem.c:18
#define NEXT_MEMORY_DESCRIPTOR(Descriptor, DescriptorSize)
Definition: uefimem.c:15
void _exituefi(VOID)
VOID UefiPrepareForReactOS(VOID)
Definition: uefimem.c:283
_In_ WDFCOLLECTION _In_ ULONG Index
_Must_inspect_result_ _In_ WDFCMRESLIST List
Definition: wdfresource.h:550
ULONG PFN_COUNT
Definition: mmtypes.h:102