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