ReactOS  0.4.14-dev-599-g2d4d3f5
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>
15 DBG_DEFAULT_CHANNEL(WINDOWS);
16 
18 
19 static 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 
46 static 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 
64 VOID
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 */
89  if (MadCount >= MAX_MAD_COUNT)
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 
105 VOID
107  PFN_NUMBER BasePage,
108  PFN_NUMBER PageCount,
109  ULONG Type)
110 {
111  BOOLEAN Status = TRUE;
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 */
122  case LoaderLoadedProgram:
123  case LoaderOsloaderStack:
125  /* Map these pages into user mode */
126  Status = MempSetupPaging(BasePage, PageCount, FALSE);
127  break;
128 
129  /* Pages used by the kernel */
131  case LoaderSystemBlock:
133  case LoaderSystemCode:
134  case LoaderHalCode:
135  case LoaderBootDriver:
143  case LoaderRegistryData:
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 */
158  case LoaderSpecialMemory:
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 
180 BOOLEAN
182 {
183  PFN_NUMBER i, PagesCount, MemoryMapSizeInPages, NoEntries;
184  PFN_NUMBER LastPageIndex, MemoryMapStartPage;
186  ULONG LastPageType;
187  //PKTSS Tss;
188  //BOOLEAN Status;
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 #if 0
233  // Always contiguously map low 1Mb of memory
234  Status = MempSetupPaging(0, 0x100, FALSE);
235  if (!Status)
236  {
237  ERR("Error during MempSetupPaging of low 1Mb\n");
238  return FALSE;
239  }
240 #endif
241 
242  /* Before creating the map, we need to map pages to kernel mode */
243  LastPageIndex = 1;
244  LastPageType = MemoryMap[1].PageAllocated;
245  for (i = 2; i < NoEntries; i++)
246  {
247  if ((MemoryMap[i].PageAllocated != LastPageType) ||
248  (i == NoEntries - 1))
249  {
250  MempSetupPagingForRegion(LastPageIndex, i - LastPageIndex, LastPageType);
251  LastPageIndex = i;
252  LastPageType = MemoryMap[i].PageAllocated;
253  }
254  }
255 
256  // Construct a good memory map from what we've got,
257  // but mark entries which the memory allocation bitmap takes
258  // as free entries (this is done in order to have the ability
259  // to place mem alloc bitmap outside lower 16Mb zone)
260  PagesCount = 1;
261  LastPageIndex = 0;
262  LastPageType = MemoryMap[0].PageAllocated;
263  for (i = 1; i < NoEntries; i++)
264  {
265  // Check if its memory map itself
266  if (i >= MemoryMapStartPage &&
267  i < (MemoryMapStartPage+MemoryMapSizeInPages))
268  {
269  // Exclude it if current page belongs to the memory map
270  MemoryMap[i].PageAllocated = LoaderFree;
271  }
272 
273  // Process entry
274  if (MemoryMap[i].PageAllocated == LastPageType &&
275  (i != NoEntries-1) )
276  {
277  PagesCount++;
278  }
279  else
280  {
281  // Add the resulting region
282  MempAddMemoryBlock(LoaderBlock, LastPageIndex, PagesCount, LastPageType);
283 
284  // Reset our counter vars
285  LastPageIndex = i;
286  LastPageType = MemoryMap[i].PageAllocated;
287  PagesCount = 1;
288  }
289  }
290 
291  // TEMP, DEBUG!
292  // adding special reserved memory zones for vmware workstation
293 #if 0
294  {
295  Mad[MadCount].BasePage = 0xfec00;
296  Mad[MadCount].PageCount = 0x10;
298  WinLdrInsertDescriptor(LoaderBlock, &Mad[MadCount]);
299  MadCount++;
300 
301  Mad[MadCount].BasePage = 0xfee00;
302  Mad[MadCount].PageCount = 0x1;
304  WinLdrInsertDescriptor(LoaderBlock, &Mad[MadCount]);
305  MadCount++;
306 
307  Mad[MadCount].BasePage = 0xfffe0;
308  Mad[MadCount].PageCount = 0x20;
310  WinLdrInsertDescriptor(LoaderBlock, &Mad[MadCount]);
311  MadCount++;
312  }
313 #endif
314 
315  /* Now we need to add high descriptors from the bios memory map */
316  for (i = 0; i < BiosMemoryMapEntryCount; i++)
317  {
318  /* Check if its higher than the lookup table */
320  {
321  /* Copy this descriptor */
322  MempAddMemoryBlock(LoaderBlock,
326  }
327  }
328 
329  TRACE("MadCount: %d\n", MadCount);
330 
331  WinLdrpDumpMemoryDescriptors(LoaderBlock); //FIXME: Delete!
332 
333  // Map our loader image, so we can continue running
334  /*Status = MempSetupPaging(OsLoaderBase >> MM_PAGE_SHIFT, OsLoaderSize >> MM_PAGE_SHIFT);
335  if (!Status)
336  {
337  UiMessageBox("Error during MempSetupPaging.");
338  return;
339  }*/
340 
341  // Fill the memory descriptor list and
342  //PrepareMemoryDescriptorList();
343  TRACE("Memory Descriptor List prepared, printing PDE\n");
344  List_PaToVa(&LoaderBlock->MemoryDescriptorListHead);
345 
346 #if DBG
347  MempDump();
348 #endif
349 
350  return TRUE;
351 }
352 
353 // Two special things this func does: it sorts descriptors,
354 // and it merges free ones
355 static VOID
358 {
359  PLIST_ENTRY ListHead = &LoaderBlock->MemoryDescriptorListHead;
360  PLIST_ENTRY PreviousEntry, NextEntry;
361  PMEMORY_ALLOCATION_DESCRIPTOR PreviousDescriptor = NULL, NextDescriptor = NULL;
362 
363  TRACE("BP=0x%X PC=0x%X %s\n", NewDescriptor->BasePage,
364  NewDescriptor->PageCount, MemTypeDesc[NewDescriptor->MemoryType]);
365 
366  /* Find a place where to insert the new descriptor to */
367  PreviousEntry = ListHead;
368  NextEntry = ListHead->Flink;
369  while (NextEntry != ListHead)
370  {
371  NextDescriptor = CONTAINING_RECORD(NextEntry,
373  ListEntry);
374  if (NewDescriptor->BasePage < NextDescriptor->BasePage)
375  break;
376 
377  PreviousEntry = NextEntry;
378  PreviousDescriptor = NextDescriptor;
379  NextEntry = NextEntry->Flink;
380  }
381 
382  /* Don't forget about merging free areas */
383  if (NewDescriptor->MemoryType != LoaderFree)
384  {
385  /* Just insert, nothing to merge */
386  InsertHeadList(PreviousEntry, &NewDescriptor->ListEntry);
387  }
388  else
389  {
390  /* Previous block also free? */
391  if ((PreviousEntry != ListHead) && (PreviousDescriptor->MemoryType == LoaderFree) &&
392  ((PreviousDescriptor->BasePage + PreviousDescriptor->PageCount) ==
393  NewDescriptor->BasePage))
394  {
395  /* Just enlarge previous descriptor's PageCount */
396  PreviousDescriptor->PageCount += NewDescriptor->PageCount;
397  NewDescriptor = PreviousDescriptor;
398  }
399  else
400  {
401  /* Nope, just insert */
402  InsertHeadList(PreviousEntry, &NewDescriptor->ListEntry);
403  }
404 
405  /* Next block is free ?*/
406  if ((NextEntry != ListHead) &&
407  (NextDescriptor->MemoryType == LoaderFree) &&
408  ((NewDescriptor->BasePage + NewDescriptor->PageCount) == NextDescriptor->BasePage))
409  {
410  /* Enlarge next descriptor's PageCount */
411  NewDescriptor->PageCount += NextDescriptor->PageCount;
412  RemoveEntryList(&NextDescriptor->ListEntry);
413  }
414  }
415 
416  return;
417 }
VOID MempDump(VOID)
Definition: winldr.c:429
#define IN
Definition: typedefs.h:38
PFN_NUMBER MmHighestPhysicalPage
Definition: meminit.c:31
#define TRUE
Definition: types.h:120
Type
Definition: Type.h:6
ULONG MadCount
Definition: wlmemory.c:58
DBG_DEFAULT_CHANNEL(WINDOWS)
VOID List_PaToVa(_In_ LIST_ENTRY *ListEntry)
FORCEINLINE VOID InsertHeadList(_Inout_ PLIST_ENTRY ListHead, _Inout_ __drv_aliasesMem PLIST_ENTRY Entry)
Definition: rtlfuncs.h:201
BIOS_MEMORY_MAP MemoryMap[32]
Definition: loader.c:11
TYPE_OF_MEMORY MemoryType
Definition: mm.h:38
VOID MempSetupPagingForRegion(PFN_NUMBER BasePage, PFN_NUMBER PageCount, ULONG Type)
Definition: wlmemory.c:106
BOOLEAN MempSetupPaging(IN PFN_NUMBER StartPage, IN PFN_NUMBER NumberOfPages, IN BOOLEAN KernelMapping)
Definition: winldr.c:170
_In_opt_ PSECURITY_DESCRIPTOR _Out_ PSECURITY_DESCRIPTOR * NewDescriptor
Definition: sefuncs.h:29
MEMORY_ALLOCATION_DESCRIPTOR * Mad
Definition: wlmemory.c:57
FORCEINLINE BOOLEAN RemoveEntryList(_In_ PLIST_ENTRY Entry)
Definition: rtlfuncs.h:105
TYPE_OF_MEMORY MemoryType
Definition: arc.h:193
PFN_NUMBER MmLowestPhysicalPage
Definition: meminit.c:30
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
ULONG PFN_NUMBER
Definition: ke.h:8
#define MAX_MAD_COUNT
Definition: wlmemory.c:60
Definition: arc.h:130
VOID UiMessageBox(PCSTR Format,...)
Definition: ui.c:320
unsigned char BOOLEAN
static const PCSTR MemTypeDesc[]
Definition: wlmemory.c:19
smooth NULL
Definition: ftsmooth.c:416
PFLT_MESSAGE_WAITER_QUEUE CONTAINING_RECORD(Csq, DEVICE_EXTENSION, IrpQueue)) -> WaiterQ.mLock) _IRQL_raises_(DISPATCH_LEVEL) VOID NTAPI FltpAcquireMessageWaiterLock(_In_ PIO_CSQ Csq, _Out_ PKIRQL Irql)
Definition: Messaging.c:560
PFN_NUMBER BasePage
Definition: mm.h:39
ULONG BiosMemoryMapEntryCount
Definition: meminit.c:34
struct _LIST_ENTRY * Flink
Definition: typedefs.h:119
#define TRACE(s)
Definition: solgame.cpp:4
PPAGE_LOOKUP_TABLE_ITEM MmGetMemoryMap(PFN_NUMBER *NoEntries)
Definition: mm.c:297
VOID FrLdrHeapCleanupAll(VOID)
Definition: heap.c:248
PFREELDR_MEMORY_DESCRIPTOR BiosMemoryMap
Definition: meminit.c:33
PVOID MmAllocateMemoryWithType(SIZE_T MemorySize, TYPE_OF_MEMORY MemoryType)
Definition: mm.c:31
Definition: typedefs.h:117
VOID WinLdrpDumpMemoryDescriptors(PLOADER_PARAMETER_BLOCK LoaderBlock)
Definition: winldr.c:1006
Status
Definition: gdiplustypes.h:24
VOID MempAddMemoryBlock(IN OUT PLOADER_PARAMETER_BLOCK LoaderBlock, PFN_NUMBER BasePage, PFN_NUMBER PageCount, ULONG Type)
Definition: wlmemory.c:65
#define ERR(fmt,...)
Definition: debug.h:109
BOOLEAN WinLdrSetupMemoryLayout(IN OUT PLOADER_PARAMETER_BLOCK LoaderBlock)
Definition: wlmemory.c:181
ULONG LoaderPagesSpanned
Definition: mm.c:29
#define OUT
Definition: typedefs.h:39
unsigned int ULONG
Definition: retypes.h:1
#define ULONG_PTR
Definition: config.h:101
const char * PCSTR
Definition: typedefs.h:51
static VOID WinLdrInsertDescriptor(IN OUT PLOADER_PARAMETER_BLOCK LoaderBlock, IN PMEMORY_ALLOCATION_DESCRIPTOR NewDescriptor)
Definition: wlmemory.c:356
PFN_NUMBER PageCount
Definition: mm.h:40