ReactOS 0.4.16-dev-974-g5022a45
wlmemory.c
Go to the documentation of this file.
1/*
2 * PROJECT: EFI Windows Loader
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: boot/freeldr/freeldr/windows/wlmemory.c
5 * PURPOSE: Memory related routines
6 * PROGRAMMERS: Aleksey Bragin (aleksey@reactos.org)
7 */
8
9/* INCLUDES ***************************************************************/
10
11#include <freeldr.h>
12#include "winldr.h"
13
14#include <debug.h>
16
17static const PCSTR MemTypeDesc[] = {
18 "ExceptionBlock ", // ?
19 "SystemBlock ", // ?
20 "Free ",
21 "Bad ", // used
22 "LoadedProgram ", // == Free
23 "FirmwareTemporary ", // == Free
24 "FirmwarePermanent ", // == Bad
25 "OsloaderHeap ", // used
26 "OsloaderStack ", // == Free
27 "SystemCode ",
28 "HalCode ",
29 "BootDriver ", // not used
30 "ConsoleInDriver ", // ?
31 "ConsoleOutDriver ", // ?
32 "StartupDpcStack ", // ?
33 "StartupKernelStack", // ?
34 "StartupPanicStack ", // ?
35 "StartupPcrPage ", // ?
36 "StartupPdrPage ", // ?
37 "RegistryData ", // used
38 "MemoryData ", // not used
39 "NlsData ", // used
40 "SpecialMemory ", // == Bad
41 "BBTMemory " // == Bad
42 };
43
44static VOID
47
48/* GLOBALS ***************************************************************/
49
52/* 200 MADs fit into 1 page, that should really be enough! */
53#define MAX_MAD_COUNT 200
54
55/* FUNCTIONS **************************************************************/
56
57VOID
59 PFN_NUMBER BasePage,
60 PFN_NUMBER PageCount,
61 ULONG Type)
62{
63 TRACE("MempAddMemoryBlock(BasePage=0x%lx, PageCount=0x%lx, Type=%ld)\n",
64 BasePage, PageCount, Type);
65
66 /* Check for memory block after 4GB - we don't support it yet
67 Note: Even last page before 4GB limit is not supported */
68 if (BasePage >= MM_MAX_PAGE)
69 {
70 /* Just skip this, without even adding to MAD list */
71 return;
72 }
73
74 /* Check if last page is after 4GB limit and shorten this block if needed */
75 if (BasePage + PageCount > MM_MAX_PAGE)
76 {
77 /* Shorten this block */
78 PageCount = MM_MAX_PAGE - BasePage;
79 }
80
81 /* Check if we have slots left */
83 {
84 ERR("Error: no MAD slots left!\n");
85 return;
86 }
87
88 /* Set Base page, page count and type */
89 Mad[MadCount].BasePage = BasePage;
90 Mad[MadCount].PageCount = PageCount;
92
93 /* Add descriptor */
94 WinLdrInsertDescriptor(LoaderBlock, &Mad[MadCount]);
95 MadCount++;
96}
97
98VOID
100 PFN_NUMBER BasePage,
101 PFN_NUMBER PageCount,
102 ULONG Type)
103{
105
106 TRACE("MempSetupPagingForRegion(BasePage=0x%lx, PageCount=0x%lx, Type=%ld)\n",
107 BasePage, PageCount, Type);
108
109 /* Make sure we don't map too high */
110 if (BasePage + PageCount > MmGetLoaderPagesSpanned()) return;
111
112 switch (Type)
113 {
114 /* Pages used by the loader */
118 /* Map these pages into user mode */
119 Status = MempSetupPaging(BasePage, PageCount, FALSE);
120 break;
121
122 /* Pages used by the kernel */
126 case LoaderSystemCode:
127 case LoaderHalCode:
128 case LoaderBootDriver:
137 case LoaderMemoryData:
138 case LoaderNlsData:
139 case LoaderXIPRom:
140 case LoaderOsloaderHeap: // FIXME
141 /* Map these pages into kernel mode */
142 Status = MempSetupPaging(BasePage, PageCount, TRUE);
143 break;
144
145 /* Pages not in use */
146 case LoaderFree:
147 case LoaderBad:
148 break;
149
150 /* Invisible to kernel */
153 case LoaderBBTMemory:
154 break;
155
156 // FIXME: not known (not used anyway)
157 case LoaderReserve:
160 break;
161 }
162
163 if (!Status)
164 {
165 ERR("Error during MempSetupPaging\n");
166 }
167}
168
169#ifdef _M_ARM
170#define PKTSS PVOID
171#endif
172
175{
176 PFN_NUMBER i, PagesCount, MemoryMapSizeInPages, NoEntries;
177 PFN_NUMBER LastPageIndex, MemoryMapStartPage;
179 ULONG LastPageType;
180 //PKTSS Tss;
182
183 /* Cleanup heap */
185
186 //
187 // Creating a suitable memory map for Windows can be tricky, so let's
188 // give a few advices:
189 // 1) One must not map the whole available memory pages to PDE!
190 // Map only what's needed - 16Mb, 24Mb, 32Mb max I think,
191 // thus occupying 4, 6 or 8 PDE entries for identical mapping,
192 // the same quantity for KSEG0_BASE mapping, one more entry for
193 // hyperspace and one more entry for HAL physical pages mapping.
194 // 2) Memory descriptors must map *the whole* physical memory
195 // showing any memory above 16/24/32 as FirmwareTemporary
196 //
197 // 3) Overall memory blocks count must not exceed 30 (?? why?)
198 //
199
200 //
201 // During MmInitMachineDependent, the kernel zeroes PDE at the following address
202 // 0xC0300000 - 0xC03007FC
203 //
204 // Then it finds the best place for non-paged pool:
205 // StartPde C0300F70, EndPde C0300FF8, NumberOfPages C13, NextPhysPage 3AD
206 //
207
208 // Allocate memory for memory allocation descriptors
211
212 // Setup an entry for each descriptor
213 MemoryMap = MmGetMemoryMap(&NoEntries);
214 if (MemoryMap == NULL)
215 {
216 UiMessageBox("Can not retrieve the current memory map.");
217 return FALSE;
218 }
219
220 // Calculate parameters of the memory map
221 MemoryMapStartPage = (ULONG_PTR)MemoryMap >> MM_PAGE_SHIFT;
222 MemoryMapSizeInPages = (NoEntries * sizeof(PAGE_LOOKUP_TABLE_ITEM) + MM_PAGE_SIZE - 1) / MM_PAGE_SIZE;
223
224 TRACE("Got memory map with %d entries\n", NoEntries);
225
226 // Always map first page of memory
228 if (!Status)
229 {
230 ERR("Error during MempSetupPaging of first page\n");
231 return FALSE;
232 }
233
234 /* Before creating the map, we need to map pages to kernel mode */
235 LastPageIndex = 1;
236 LastPageType = MemoryMap[1].PageAllocated;
237 for (i = 2; i < NoEntries; i++)
238 {
239 if ((MemoryMap[i].PageAllocated != LastPageType) ||
240 (i == NoEntries - 1))
241 {
242 MempSetupPagingForRegion(LastPageIndex, i - LastPageIndex, LastPageType);
243 LastPageIndex = i;
244 LastPageType = MemoryMap[i].PageAllocated;
245 }
246 }
247
248 // Construct a good memory map from what we've got,
249 // but mark entries which the memory allocation bitmap takes
250 // as free entries (this is done in order to have the ability
251 // to place mem alloc bitmap outside lower 16Mb zone)
252 PagesCount = 1;
253 LastPageIndex = 0;
254 LastPageType = MemoryMap[0].PageAllocated;
255 for (i = 1; i < NoEntries; i++)
256 {
257 // Check if its memory map itself
258 if (i >= MemoryMapStartPage &&
259 i < (MemoryMapStartPage+MemoryMapSizeInPages))
260 {
261 // Exclude it if current page belongs to the memory map
262 MemoryMap[i].PageAllocated = LoaderFree;
263 }
264
265 // Process entry
266 if (MemoryMap[i].PageAllocated == LastPageType &&
267 (i != NoEntries-1) )
268 {
269 PagesCount++;
270 }
271 else
272 {
273 // Add the resulting region
274 MempAddMemoryBlock(LoaderBlock, LastPageIndex, PagesCount, LastPageType);
275
276 // Reset our counter vars
277 LastPageIndex = i;
278 LastPageType = MemoryMap[i].PageAllocated;
279 PagesCount = 1;
280 }
281 }
282
283 // TEMP, DEBUG!
284 // adding special reserved memory zones for vmware workstation
285#if 0
286 {
287 Mad[MadCount].BasePage = 0xfec00;
288 Mad[MadCount].PageCount = 0x10;
290 WinLdrInsertDescriptor(LoaderBlock, &Mad[MadCount]);
291 MadCount++;
292
293 Mad[MadCount].BasePage = 0xfee00;
294 Mad[MadCount].PageCount = 0x1;
296 WinLdrInsertDescriptor(LoaderBlock, &Mad[MadCount]);
297 MadCount++;
298
299 Mad[MadCount].BasePage = 0xfffe0;
300 Mad[MadCount].PageCount = 0x20;
302 WinLdrInsertDescriptor(LoaderBlock, &Mad[MadCount]);
303 MadCount++;
304 }
305#endif
308
310
311 /* Now we need to add high descriptors from the bios memory map */
312 for (i = 0; i < BiosMemoryMapEntryCount; i++)
313 {
314 /* Check if its higher than the lookup table */
316 {
317 /* Copy this descriptor */
318 MempAddMemoryBlock(LoaderBlock,
322 }
323 }
324
325 TRACE("MadCount: %d\n", MadCount);
326
327 WinLdrpDumpMemoryDescriptors(LoaderBlock); //FIXME: Delete!
328
329 // Map our loader image, so we can continue running
330 /*Status = MempSetupPaging(OsLoaderBase >> MM_PAGE_SHIFT, OsLoaderSize >> MM_PAGE_SHIFT);
331 if (!Status)
332 {
333 UiMessageBox("Error during MempSetupPaging.");
334 return;
335 }*/
336
337 // Fill the memory descriptor list and
338 //PrepareMemoryDescriptorList();
339 TRACE("Memory Descriptor List prepared, printing PDE\n");
340 List_PaToVa(&LoaderBlock->MemoryDescriptorListHead);
341
342#if DBG
343 MempDump();
344#endif
345
346 return TRUE;
347}
348
349// Two special things this func does: it sorts descriptors,
350// and it merges free ones
351static VOID
354{
355 PLIST_ENTRY ListHead = &LoaderBlock->MemoryDescriptorListHead;
356 PLIST_ENTRY PreviousEntry, NextEntry;
357 PMEMORY_ALLOCATION_DESCRIPTOR PreviousDescriptor = NULL, NextDescriptor = NULL;
358
359 TRACE("BP=0x%X PC=0x%X %s\n", NewDescriptor->BasePage,
360 NewDescriptor->PageCount, MemTypeDesc[NewDescriptor->MemoryType]);
361
362 /* Find a place where to insert the new descriptor to */
363 PreviousEntry = ListHead;
364 NextEntry = ListHead->Flink;
365 while (NextEntry != ListHead)
366 {
367 NextDescriptor = CONTAINING_RECORD(NextEntry,
369 ListEntry);
370 if (NewDescriptor->BasePage < NextDescriptor->BasePage)
371 break;
372
373 PreviousEntry = NextEntry;
374 PreviousDescriptor = NextDescriptor;
375 NextEntry = NextEntry->Flink;
376 }
377
378 /* Don't forget about merging free areas */
379 if (NewDescriptor->MemoryType != LoaderFree)
380 {
381 /* Just insert, nothing to merge */
382 InsertHeadList(PreviousEntry, &NewDescriptor->ListEntry);
383 }
384 else
385 {
386 /* Previous block also free? */
387 if ((PreviousEntry != ListHead) && (PreviousDescriptor->MemoryType == LoaderFree) &&
388 ((PreviousDescriptor->BasePage + PreviousDescriptor->PageCount) ==
389 NewDescriptor->BasePage))
390 {
391 /* Just enlarge previous descriptor's PageCount */
392 PreviousDescriptor->PageCount += NewDescriptor->PageCount;
393 NewDescriptor = PreviousDescriptor;
394 }
395 else
396 {
397 /* Nope, just insert */
398 InsertHeadList(PreviousEntry, &NewDescriptor->ListEntry);
399 }
400
401 /* Next block is free ?*/
402 if ((NextEntry != ListHead) &&
403 (NextDescriptor->MemoryType == LoaderFree) &&
404 ((NewDescriptor->BasePage + NewDescriptor->PageCount) == NextDescriptor->BasePage))
405 {
406 /* Enlarge next descriptor's PageCount */
407 NewDescriptor->PageCount += NextDescriptor->PageCount;
408 RemoveEntryList(&NextDescriptor->ListEntry);
409 }
410 }
411
412 return;
413}
ULONG_PTR PFN_NUMBER
unsigned char BOOLEAN
Type
Definition: Type.h:7
BOOLEAN MempSetupPaging(IN PFN_NUMBER StartPage, IN PFN_NUMBER NumberOfPages, IN BOOLEAN KernelMapping)
Definition: winldr.c:171
VOID MempDump(VOID)
Definition: winldr.c:424
#define ERR(fmt,...)
Definition: precomp.h:57
BIOS_MEMORY_MAP MemoryMap[32]
Definition: loader.c:11
#define DBG_DEFAULT_CHANNEL(ch)
Definition: debug.h:106
PVOID MmAllocateMemoryWithType(SIZE_T MemorySize, TYPE_OF_MEMORY MemoryType)
Definition: mm.c:31
ULONG MmGetBiosMemoryMap(_Out_ PFREELDR_MEMORY_DESCRIPTOR *MemoryMap)
Definition: meminit.c:38
PPAGE_LOOKUP_TABLE_ITEM MmGetMemoryMap(PFN_NUMBER *NoEntries)
Definition: mm.c:297
PFN_NUMBER MmGetHighestPhysicalPage(VOID)
Definition: meminit.c:728
PFN_NUMBER MmGetLoaderPagesSpanned(VOID)
Definition: mm.c:307
VOID FrLdrHeapCleanupAll(VOID)
Definition: heap.c:249
VOID UiMessageBox(_In_ PCSTR Format,...)
Definition: ui.c:359
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define ULONG_PTR
Definition: config.h:101
#define RemoveEntryList(Entry)
Definition: env_spec_w32.h:986
#define InsertHeadList(ListHead, Entry)
Status
Definition: gdiplustypes.h:25
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
VOID List_PaToVa(_In_ LIST_ENTRY *ListEntry)
PFREELDR_MEMORY_DESCRIPTOR BiosMemoryMap
Definition: meminit.c:33
ULONG BiosMemoryMapEntryCount
Definition: meminit.c:34
@ LoaderBad
Definition: arc.h:177
@ LoaderMemoryData
Definition: arc.h:194
@ LoaderReserve
Definition: arc.h:198
@ LoaderBootDriver
Definition: arc.h:185
@ LoaderOsloaderHeap
Definition: arc.h:181
@ LoaderFree
Definition: arc.h:176
@ LoaderConsoleInDriver
Definition: arc.h:186
@ LoaderFirmwareTemporary
Definition: arc.h:179
@ LoaderLoadedProgram
Definition: arc.h:178
@ LoaderSystemCode
Definition: arc.h:183
@ LoaderNlsData
Definition: arc.h:195
@ LoaderLargePageFiller
Definition: arc.h:201
@ LoaderStartupDpcStack
Definition: arc.h:188
@ LoaderHALCachedMemory
Definition: arc.h:200
@ LoaderRegistryData
Definition: arc.h:193
@ LoaderHalCode
Definition: arc.h:184
@ LoaderFirmwarePermanent
Definition: arc.h:180
@ LoaderErrorLogMemory
Definition: arc.h:202
@ LoaderStartupPcrPage
Definition: arc.h:191
@ LoaderOsloaderStack
Definition: arc.h:182
@ LoaderSpecialMemory
Definition: arc.h:196
@ LoaderSystemBlock
Definition: arc.h:175
@ LoaderStartupPdrPage
Definition: arc.h:192
@ LoaderExceptionBlock
Definition: arc.h:174
@ LoaderXIPRom
Definition: arc.h:199
@ LoaderStartupKernelStack
Definition: arc.h:189
@ LoaderStartupPanicStack
Definition: arc.h:190
@ LoaderConsoleOutDriver
Definition: arc.h:187
@ LoaderBBTMemory
Definition: arc.h:197
#define TRACE(s)
Definition: solgame.cpp:4
TYPE_OF_MEMORY MemoryType
Definition: mm.h:43
PFN_NUMBER PageCount
Definition: mm.h:45
PFN_NUMBER BasePage
Definition: mm.h:44
Definition: typedefs.h:120
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
TYPE_OF_MEMORY MemoryType
Definition: arc.h:240
const char * PCSTR
Definition: typedefs.h:52
#define IN
Definition: typedefs.h:39
#define CONTAINING_RECORD(address, type, field)
Definition: typedefs.h:260
uint32_t ULONG
Definition: typedefs.h:59
#define OUT
Definition: typedefs.h:40
VOID WinLdrpDumpMemoryDescriptors(PLOADER_PARAMETER_BLOCK LoaderBlock)
Definition: winldr.c:1288
#define MAX_MAD_COUNT
Definition: wlmemory.c:53
MEMORY_ALLOCATION_DESCRIPTOR * Mad
Definition: wlmemory.c:50
BOOLEAN WinLdrSetupMemoryLayout(IN OUT PLOADER_PARAMETER_BLOCK LoaderBlock)
Definition: wlmemory.c:174
static const PCSTR MemTypeDesc[]
Definition: wlmemory.c:17
static VOID WinLdrInsertDescriptor(IN OUT PLOADER_PARAMETER_BLOCK LoaderBlock, IN PMEMORY_ALLOCATION_DESCRIPTOR NewDescriptor)
Definition: wlmemory.c:352
VOID MempSetupPagingForRegion(PFN_NUMBER BasePage, PFN_NUMBER PageCount, ULONG Type)
Definition: wlmemory.c:99
VOID MempAddMemoryBlock(IN OUT PLOADER_PARAMETER_BLOCK LoaderBlock, PFN_NUMBER BasePage, PFN_NUMBER PageCount, ULONG Type)
Definition: wlmemory.c:58
ULONG MadCount
Definition: wlmemory.c:51
_In_opt_ PSECURITY_DESCRIPTOR _Out_ PSECURITY_DESCRIPTOR * NewDescriptor
Definition: sefuncs.h:30