ReactOS  0.4.13-dev-257-gfabbd7c
pcmem.c File Reference
#include <freeldr.h>
#include <arch/pc/x86common.h>
#include <debug.h>
Include dependency graph for pcmem.c:

Go to the source code of this file.

Macros

#define ULONGLONG_ALIGN_DOWN_BY(size, align)   ((ULONGLONG)(size) & ~((ULONGLONG)(align) - 1))
 
#define ULONGLONG_ALIGN_UP_BY(size, align)   (ULONGLONG_ALIGN_DOWN_BY(((ULONGLONG)(size) + align - 1), align))
 
#define MAX_BIOS_DESCRIPTORS   80ul
 

Functions

 DBG_DEFAULT_CHANNEL (MEMORY)
 
ULONG AddMemoryDescriptor (IN OUT PFREELDR_MEMORY_DESCRIPTOR List, IN ULONG MaxCount, IN PFN_NUMBER BasePage, IN PFN_NUMBER PageCount, IN TYPE_OF_MEMORY MemoryType)
 
static BOOLEAN GetExtendedMemoryConfiguration (ULONG *pMemoryAtOneMB, ULONG *pMemoryAtSixteenMB)
 
static ULONG PcMemGetConventionalMemorySize (VOID)
 
static BOOLEAN GetEbdaLocation (PULONG BaseAddress, PULONG Size)
 
static VOID PcMemCheckUsableMemorySize (VOID)
 
static ULONG PcMemGetBiosMemoryMap (PFREELDR_MEMORY_DESCRIPTOR MemoryMap, ULONG MaxMemoryMapSize)
 
VOID ReserveMemory (ULONG_PTR BaseAddress, SIZE_T Size, TYPE_OF_MEMORY MemoryType, PCHAR Usage)
 
VOID SetMemory (ULONG_PTR BaseAddress, SIZE_T Size, TYPE_OF_MEMORY MemoryType)
 
PFREELDR_MEMORY_DESCRIPTOR PcMemGetMemoryMap (ULONG *MemoryMapSize)
 

Variables

BIOS_MEMORY_MAP PcBiosMemoryMap [MAX_BIOS_DESCRIPTORS]
 
ULONG PcBiosMapCount
 
FREELDR_MEMORY_DESCRIPTOR PcMemoryMap [MAX_BIOS_DESCRIPTORS+1]
 
ULONG PcMapCount
 

Macro Definition Documentation

◆ MAX_BIOS_DESCRIPTORS

#define MAX_BIOS_DESCRIPTORS   80ul

Definition at line 38 of file pcmem.c.

◆ ULONGLONG_ALIGN_DOWN_BY

#define ULONGLONG_ALIGN_DOWN_BY (   size,
  align 
)    ((ULONGLONG)(size) & ~((ULONGLONG)(align) - 1))

Definition at line 32 of file pcmem.c.

◆ ULONGLONG_ALIGN_UP_BY

#define ULONGLONG_ALIGN_UP_BY (   size,
  align 
)    (ULONGLONG_ALIGN_DOWN_BY(((ULONGLONG)(size) + align - 1), align))

Definition at line 35 of file pcmem.c.

Function Documentation

◆ AddMemoryDescriptor()

ULONG AddMemoryDescriptor ( IN OUT PFREELDR_MEMORY_DESCRIPTOR  List,
IN ULONG  MaxCount,
IN PFN_NUMBER  BasePage,
IN PFN_NUMBER  PageCount,
IN TYPE_OF_MEMORY  MemoryType 
)

Definition at line 102 of file meminit.c.

108 {
109  ULONG Index, DescriptCount;
111  TRACE("AddMemoryDescriptor(0x%Ix, 0x%Ix, %u)\n",
112  BasePage, PageCount, MemoryType);
113 
114  EndPage = BasePage + PageCount;
115 
116  /* Skip over all descriptor below the new range */
117  Index = 0;
118  while ((List[Index].PageCount != 0) &&
119  ((List[Index].BasePage + List[Index].PageCount) <= BasePage))
120  {
121  Index++;
122  }
123 
124  /* Count the descriptors */
125  DescriptCount = Index;
126  while (List[DescriptCount].PageCount != 0)
127  {
128  DescriptCount++;
129  }
130 
131  /* Check if the existing range conflicts with the new range */
132  while ((List[Index].PageCount != 0) &&
133  (List[Index].BasePage < EndPage))
134  {
135  TRACE("AddMemoryDescriptor conflict @%lu: new=[%lx:%lx], existing=[%lx,%lx]\n",
136  Index, BasePage, PageCount, List[Index].BasePage, List[Index].PageCount);
137 
138  /*
139  * We have 4 overlapping cases:
140  *
141  * Case (a) (b) (c) (d)
142  * Existing range |---| |-----| |---| |---|
143  * New range |---| |---| |-----| |---|
144  *
145  */
146 
147  /* Check if the existing range starts before the new range (a)/(b) */
148  if (List[Index].BasePage < BasePage)
149  {
150  /* Check if the existing range extends beyond the new range (b) */
151  if (List[Index].BasePage + List[Index].PageCount > EndPage)
152  {
153  /* Split the descriptor */
154  RtlMoveMemory(&List[Index + 1],
155  &List[Index],
156  (DescriptCount - Index) * sizeof(List[0]));
157  List[Index + 1].BasePage = EndPage;
158  List[Index + 1].PageCount = List[Index].BasePage +
159  List[Index].PageCount -
160  List[Index + 1].BasePage;
161  List[Index].PageCount = BasePage - List[Index].BasePage;
162  Index++;
163  DescriptCount++;
164  break;
165  }
166  else
167  {
168  /* Crop the existing range and continue with the next range */
169  List[Index].PageCount = BasePage - List[Index].BasePage;
170  Index++;
171  }
172  }
173  /* Check if the existing range is fully covered by the new range (c) */
174  else if ((List[Index].BasePage + List[Index].PageCount) <=
175  EndPage)
176  {
177  /* Delete this descriptor */
179  &List[Index + 1],
180  (DescriptCount - Index) * sizeof(List[0]));
181  DescriptCount--;
182  }
183  /* Otherwise the existing range ends after the new range (d) */
184  else
185  {
186  /* Crop the existing range at the start and bail out */
187  List[Index].PageCount -= EndPage - List[Index].BasePage;
188  List[Index].BasePage = EndPage;
189  break;
190  }
191  }
192 
193  /* Make sure we can still add a new descriptor */
194  if (DescriptCount >= MaxCount)
195  {
198  __FILE__,
199  __LINE__,
200  "Ran out of static memory descriptors!");
201  }
202 
203  /* Insert the new descriptor */
204  if (Index < DescriptCount)
205  {
206  RtlMoveMemory(&List[Index + 1],
207  &List[Index],
208  (DescriptCount - Index) * sizeof(List[0]));
209  }
210 
211  List[Index].BasePage = BasePage;
212  List[Index].PageCount = PageCount;
213  List[Index].MemoryType = MemoryType;
214  DescriptCount++;
215 
216 #if 0 // only enable on demand!
217  DbgDumpMemoryMap(List);
218 #endif
219  return DescriptCount;
220 }
int WINAPI EndPage(_In_ HDC)
#define RtlMoveMemory(Destination, Source, Length)
Definition: typedefs.h:263
ULONG PFN_NUMBER
Definition: ke.h:8
#define TRACE(s)
Definition: solgame.cpp:4
LIST_ENTRY List
Definition: psmgr.c:57
static const UCHAR Index[8]
Definition: usbohci.c:18
VOID FrLdrBugCheckWithMessage(ULONG BugCode, PCHAR File, ULONG Line, PSTR Format,...)
Definition: entry.c:23
unsigned int ULONG
Definition: retypes.h:1

Referenced by PcMemGetBiosMemoryMap(), PcMemGetMemoryMap(), ReserveMemory(), and SetMemory().

◆ DBG_DEFAULT_CHANNEL()

DBG_DEFAULT_CHANNEL ( MEMORY  )

◆ GetEbdaLocation()

static BOOLEAN GetEbdaLocation ( PULONG  BaseAddress,
PULONG  Size 
)
static

Definition at line 178 of file pcmem.c.

181 {
182  REGS Regs;
183 
184  TRACE("GetEbdaLocation()\n");
185 
186  /* Get the address of the Extended BIOS Data Area (EBDA).
187  * Int 15h, AH=C1h
188  * SYSTEM - RETURN EXTENDED-BIOS DATA-AREA SEGMENT ADDRESS (PS)
189  *
190  * Return:
191  * CF set on error
192  * CF clear if successful
193  * ES = segment of data area
194  */
195  Regs.x.eax = 0x0000C100;
196  Int386(0x15, &Regs, &Regs);
197 
198  /* If the function fails, there is no EBDA */
199  if (!INT386_SUCCESS(Regs))
200  {
201  return FALSE;
202  }
203 
204  /* Get Base address and (maximum) size */
205  *BaseAddress = (ULONG)Regs.w.es << 4;
206  *Size = 0xA0000 - *BaseAddress;
207  return TRUE;
208 }
#define TRUE
Definition: types.h:120
unsigned long eax
Definition: pcbios.h:71
DWORDREGS x
Definition: pcbios.h:140
unsigned short es
Definition: pcbios.h:101
int __cdecl Int386(int ivec, REGS *in, REGS *out)
#define INT386_SUCCESS(regs)
Definition: pcbios.h:159
_In_ HANDLE _Outptr_result_bytebuffer_ ViewSize PVOID * BaseAddress
Definition: mmfuncs.h:404
#define TRACE(s)
Definition: solgame.cpp:4
IN PVOID IN PVOID IN USHORT IN USHORT Size
Definition: pci.h:359
unsigned int ULONG
Definition: retypes.h:1
Definition: pcbios.h:138
WORDREGS w
Definition: pcbios.h:142

Referenced by PcMemGetMemoryMap().

◆ GetExtendedMemoryConfiguration()

static BOOLEAN GetExtendedMemoryConfiguration ( ULONG pMemoryAtOneMB,
ULONG pMemoryAtSixteenMB 
)
static

Definition at line 56 of file pcmem.c.

57 {
58  REGS RegsIn;
59  REGS RegsOut;
60 
61  TRACE("GetExtendedMemoryConfiguration()\n");
62 
63  *pMemoryAtOneMB = 0;
64  *pMemoryAtSixteenMB = 0;
65 
66  // Int 15h AX=E801h
67  // Phoenix BIOS v4.0 - GET MEMORY SIZE FOR >64M CONFIGURATIONS
68  //
69  // AX = E801h
70  // Return:
71  // CF clear if successful
72  // AX = extended memory between 1M and 16M, in K (max 3C00h = 15MB)
73  // BX = extended memory above 16M, in 64K blocks
74  // CX = configured memory 1M to 16M, in K
75  // DX = configured memory above 16M, in 64K blocks
76  // CF set on error
77  RegsIn.w.ax = 0xE801;
78  Int386(0x15, &RegsIn, &RegsOut);
79 
80  TRACE("Int15h AX=E801h\n");
81  TRACE("AX = 0x%x\n", RegsOut.w.ax);
82  TRACE("BX = 0x%x\n", RegsOut.w.bx);
83  TRACE("CX = 0x%x\n", RegsOut.w.cx);
84  TRACE("DX = 0x%x\n", RegsOut.w.dx);
85  TRACE("CF set = %s\n", (RegsOut.x.eflags & EFLAGS_CF) ? "TRUE" : "FALSE");
86 
87  if (INT386_SUCCESS(RegsOut))
88  {
89  // If AX=BX=0000h the use CX and DX
90  if (RegsOut.w.ax == 0)
91  {
92  // Return extended memory size in K
93  *pMemoryAtSixteenMB = RegsOut.w.dx;
94  *pMemoryAtOneMB = RegsOut.w.cx;
95  return TRUE;
96  }
97  else
98  {
99  // Return extended memory size in K
100  *pMemoryAtSixteenMB = RegsOut.w.bx;
101  *pMemoryAtOneMB = RegsOut.w.ax;
102  return TRUE;
103  }
104  }
105 
106  // If we get here then Int15 Func E801h didn't work
107  // So try Int15 Func 88h
108  // Int 15h AH=88h
109  // SYSTEM - GET EXTENDED MEMORY SIZE (286+)
110  //
111  // AH = 88h
112  // Return:
113  // CF clear if successful
114  // AX = number of contiguous KB starting at absolute address 100000h
115  // CF set on error
116  // AH = status
117  // 80h invalid command (PC,PCjr)
118  // 86h unsupported function (XT,PS30)
119  RegsIn.b.ah = 0x88;
120  Int386(0x15, &RegsIn, &RegsOut);
121 
122  TRACE("Int15h AH=88h\n");
123  TRACE("AX = 0x%x\n", RegsOut.w.ax);
124  TRACE("CF set = %s\n", (RegsOut.x.eflags & EFLAGS_CF) ? "TRUE" : "FALSE");
125 
126  if (INT386_SUCCESS(RegsOut) && RegsOut.w.ax != 0)
127  {
128  *pMemoryAtOneMB = RegsOut.w.ax;
129  return TRUE;
130  }
131 
132  // If we get here then Int15 Func 88h didn't work
133  // So try reading the CMOS
134  WRITE_PORT_UCHAR((PUCHAR)0x70, 0x31);
135  *pMemoryAtOneMB = READ_PORT_UCHAR((PUCHAR)0x71);
136  *pMemoryAtOneMB = (*pMemoryAtOneMB & 0xFFFF);
137  *pMemoryAtOneMB = (*pMemoryAtOneMB << 8);
138 
139  TRACE("Int15h Failed\n");
140  TRACE("CMOS reports: 0x%lx\n", *pMemoryAtOneMB);
141 
142  if (*pMemoryAtOneMB != 0)
143  {
144  return TRUE;
145  }
146 
147  return FALSE;
148 }
unsigned short dx
Definition: pcbios.h:94
#define TRUE
Definition: types.h:120
unsigned char * PUCHAR
Definition: retypes.h:3
UCHAR NTAPI READ_PORT_UCHAR(PUCHAR Address)
Definition: mach.c:535
DWORDREGS x
Definition: pcbios.h:140
unsigned short cx
Definition: pcbios.h:93
#define EFLAGS_CF
Definition: ketypes.h:123
unsigned char ah
Definition: pcbios.h:112
int __cdecl Int386(int ivec, REGS *in, REGS *out)
#define INT386_SUCCESS(regs)
Definition: pcbios.h:159
#define TRACE(s)
Definition: solgame.cpp:4
BYTEREGS b
Definition: pcbios.h:143
unsigned long eflags
Definition: pcbios.h:85
unsigned short bx
Definition: pcbios.h:92
unsigned short ax
Definition: pcbios.h:91
Definition: pcbios.h:138
void WRITE_PORT_UCHAR(PUCHAR Address, UCHAR Value)
Definition: mach.c:539
WORDREGS w
Definition: pcbios.h:142

Referenced by PcMemGetMemoryMap().

◆ PcMemCheckUsableMemorySize()

static VOID PcMemCheckUsableMemorySize ( VOID  )
static

Definition at line 212 of file pcmem.c.

213 {
215 
216  TRACE("PcMemCheckUsableMemorySize()\n");
217 
218  /* Make sure the usable memory is large enough. To do this we check the 16
219  bit value at address 0x413 inside the BDA, which gives us the usable size
220  in KB */
221  Size = (*(PUSHORT)(ULONG_PTR)0x413) * 1024;
223  if (Size < RequiredSize)
224  {
227  __FILE__,
228  __LINE__,
229  "The BIOS reported a usable memory range up to 0x%lx, which is too small!\n"
230  "Required size is 0x%lx\n\n"
231  "If you see this, please report to the ReactOS team!",
232  Size, RequiredSize);
233  }
234 }
#define FREELDR_BASE
Definition: hardware.h:18
uint32_t ULONG_PTR
Definition: typedefs.h:63
_Inout_ PRTL_BUFFER _In_ SIZE_T RequiredSize
#define TRACE(s)
Definition: solgame.cpp:4
#define PAGE_SIZE
Definition: env_spec_w32.h:49
IN PVOID IN PVOID IN USHORT IN USHORT Size
Definition: pci.h:359
VOID FrLdrBugCheckWithMessage(ULONG BugCode, PCHAR File, ULONG Line, PSTR Format,...)
Definition: entry.c:23
unsigned int ULONG
Definition: retypes.h:1
SIZE_T FrLdrImageSize
Definition: meminit.c:35
unsigned short * PUSHORT
Definition: retypes.h:2

Referenced by PcMemGetMemoryMap().

◆ PcMemGetBiosMemoryMap()

static ULONG PcMemGetBiosMemoryMap ( PFREELDR_MEMORY_DESCRIPTOR  MemoryMap,
ULONG  MaxMemoryMapSize 
)
static

Definition at line 238 of file pcmem.c.

239 {
240  REGS Regs;
241  ULONGLONG RealBaseAddress, EndAddress, RealSize;
242  TYPE_OF_MEMORY MemoryType;
243 
244  ASSERT(PcBiosMapCount == 0);
245 
246  TRACE("PcMemGetBiosMemoryMap()\n");
247 
248  /* Int 15h AX=E820h
249  * Newer BIOSes - GET SYSTEM MEMORY MAP
250  *
251  * AX = E820h
252  * EAX = 0000E820h
253  * EDX = 534D4150h ('SMAP')
254  * EBX = continuation value or 00000000h to start at beginning of map
255  * ECX = size of buffer for result, in bytes (should be >= 20 bytes)
256  * ES:DI -> buffer for result
257  * Return:
258  * CF clear if successful
259  * EAX = 534D4150h ('SMAP')
260  * ES:DI buffer filled
261  * EBX = next offset from which to copy or 00000000h if all done
262  * ECX = actual length returned in bytes
263  * CF set on error
264  * AH = error code (86h)
265  */
266  Regs.x.ebx = 0x00000000;
267 
269  {
270  /* ACPI 3.0/4.0: Set Extended Attributes to enabled/valid by default, in case entry has no E.A.. */
271  ((PBIOS_MEMORY_MAP)BIOSCALLBUFFER)->ExtendedAttributesAsULONG = 0;
272  ((PBIOS_MEMORY_MAP)BIOSCALLBUFFER)->ExtendedAttributes.Enabled_Reserved = 1;
273 
274  /* Setup the registers for the BIOS call */
275  Regs.x.eax = 0x0000E820;
276  Regs.x.edx = 0x534D4150; /* ('SMAP') */
277  /* Regs.x.ebx = 0x00000001; Continuation value already set */
278  Regs.x.ecx = sizeof(BIOS_MEMORY_MAP);
279  Regs.w.es = BIOSCALLBUFSEGMENT;
280  Regs.w.di = BIOSCALLBUFOFFSET;
281  Int386(0x15, &Regs, &Regs);
282 
283  TRACE("Memory Map Entry %lu\n", PcBiosMapCount);
284  TRACE("Int15h AX=E820h\n");
285  TRACE("EAX = 0x%lx\n", Regs.x.eax);
286  TRACE("EBX = 0x%lx\n", Regs.x.ebx);
287  TRACE("ECX = %lu\n", Regs.x.ecx);
288  TRACE("CF set = %s\n", (Regs.x.eflags & EFLAGS_CF) ? "TRUE" : "FALSE");
289 
290  /* If the BIOS didn't return 'SMAP' in EAX then
291  * it doesn't support this call. */
292  if (Regs.x.eax != 0x534D4150)
293  {
294  WARN("BIOS doesn't support Int15h AX=E820h!\n");
295  break;
296  }
297 
298  /* If the carry flag is set,
299  * then this call was past the last entry, so we're done. */
300  if (!INT386_SUCCESS(Regs))
301  {
302  TRACE("End of System Memory Map! (Past last)\n");
303  break;
304  }
305 
306  if (Regs.x.ecx == 0)
307  {
308  TRACE("Discard empty entry. (would-be-PcBiosMapCount = %lu)\n",
310  goto nextRange;
311  }
312 
313  /* Extra safety: unexpected entry length.
314  * All in-between values are valid too, as x86 is little-indian
315  * and only lower byte is used per ACPI 6.2-A.
316  */
318  Regs.x.ecx > sizeof(BIOS_MEMORY_MAP))
319  {
320  ERR("Int 15h AX=E820h returned an invalid entry length! (would-be-PcBiosMapCount = %lu, Entry length = (%Iu <=) %lu (<= %Iu))\n",
322  /* Warn user, unless wrong case is "first and not too big entry", which is otherwise harmless. */
323  if (PcBiosMapCount > 0 || Regs.x.ecx > sizeof(BIOS_MEMORY_MAP))
324  {
325  ASSERTMSG("Int 15h AX=E820h returned an invalid entry length!\n", FALSE);
326  }
327  /* We keep previous entries (if any), but do not dare trying next entries.
328  * We assume these entries are good to use as is. If they are not, we are in trouble...
329  * (And don't ask what happens if BIOS actually overflowed our entry buffer...)
330  *
331  * FIXME: Safer = revert previous entries, Safest = blacklist this BIOS.
332  */
333  break;
334  }
335 
336  if (((PBIOS_MEMORY_MAP)BIOSCALLBUFFER)->ExtendedAttributes.Enabled_Reserved == 0)
337  {
338  WARN("Discard disabled/invalid entry. (would-be-PcBiosMapCount = %lu)\n",
340  /* This unlikely case was correct between ACPI 3.0 and 4.0, so assume all is fine.
341  * Unless we would be ready to drop ACPI 3.0 compatibility.
342  */
343  goto nextRange;
344  }
345 
346  /* Copy data to global buffer */
348 
349  TRACE("BaseAddress: 0x%llx\n", PcBiosMemoryMap[PcBiosMapCount].BaseAddress);
350  TRACE("Length: 0x%llx\n", PcBiosMemoryMap[PcBiosMapCount].Length);
351  TRACE("Type: 0x%lx\n", PcBiosMemoryMap[PcBiosMapCount].Type);
352  TRACE("ExtendedAttributesAsULONG: 0x%08lx\n", PcBiosMemoryMap[PcBiosMapCount].ExtendedAttributesAsULONG);
353 
354  if (PcBiosMemoryMap[PcBiosMapCount].ExtendedAttributes.ErrorLog == 1)
355  {
356  FIXME("EA.ErrorLog = 1. Please report this to CORE-14150. "
357  "(PcBiosMapCount = %lu, BaseAddress = 0x%llx, Length = 0x%llx, Type = 0x%lx, ExtendedAttributesAsULONG = 0x%08lx)\n",
362  PcBiosMemoryMap[PcBiosMapCount].ExtendedAttributesAsULONG);
363  // NotWantedForPublicBuilds: ASSERTMSG("EA.ErrorLog = 1. Check/Report then CONTinue.\n", FALSE);
364  }
365 
367  {
368  TRACE("Discard empty range. (would-be-PcBiosMapCount = %lu, BaseAddress = 0x%llx, Length = 0)\n",
370  goto nextRange;
371  }
372 
373  /* Check if this is free memory */
375  {
376  MemoryType = LoaderFree;
377 
378  /* Align up base of memory range */
379  RealBaseAddress = ULONGLONG_ALIGN_UP_BY(
381  PAGE_SIZE);
382 
383  /* Calculate aligned EndAddress */
386  EndAddress = ULONGLONG_ALIGN_DOWN_BY(EndAddress, PAGE_SIZE);
387 
388  /* Check if there is anything left */
389  if (EndAddress <= RealBaseAddress)
390  {
391  /* This doesn't span any page, so continue with next range */
392  TRACE("Skipping aligned range < PAGE_SIZE. (would-be-PcBiosMapCount = %lu, BaseAddress = 0x%llx, Length = 0x%llx)\n",
396  goto nextRange;
397  }
398 
399  /* Calculate the length of the aligned range */
400  RealSize = EndAddress - RealBaseAddress;
401  }
402  else
403  {
405  {
406  MemoryType = LoaderFirmwarePermanent;
407  }
408  else
409  {
410  MemoryType = LoaderSpecialMemory;
411  }
412 
413  /* Align down base of memory area */
414  RealBaseAddress = ULONGLONG_ALIGN_DOWN_BY(
416  PAGE_SIZE);
417 
418  /* Calculate the length after aligning the base */
420  PcBiosMemoryMap[PcBiosMapCount].Length - RealBaseAddress;
421  RealSize = ULONGLONG_ALIGN_UP_BY(RealSize, PAGE_SIZE);
422  }
423 
424  /* Check if we can add this descriptor */
425  if (RealSize < MM_PAGE_SIZE)
426  {
427  TRACE("Skipping aligned range < MM_PAGE_SIZE. (PcBiosMapCount = %lu, BaseAddress = 0x%llx, Length = 0x%llx)\n",
431  }
432  else if (PcMapCount >= MaxMemoryMapSize)
433  {
434  ERR("PcMemoryMap is already full! (PcBiosMapCount = %lu, PcMapCount = %lu (>= %lu))\n",
435  PcBiosMapCount, PcMapCount, MaxMemoryMapSize);
436  // NotWantedForPublicBuilds: ASSERTMSG("PcMemoryMap is already full!\n", FALSE);
437  /* We keep previous entries, and half-retrieve current/next entries.
438  * We assume all these entries are good to use as is. If they are not, we are in trouble...
439  *
440  * FIXME: Safer = revert (half-)retrieved entries, Safest = increase MaxMemoryMapSize.
441  */
442  }
443  else
444  {
445  /* Add the descriptor */
448  (PFN_NUMBER)(RealBaseAddress / MM_PAGE_SIZE),
449  (PFN_NUMBER)(RealSize / MM_PAGE_SIZE),
450  MemoryType);
451  }
452 
453  PcBiosMapCount++;
454 
455 nextRange:
456  /* If the continuation value is zero,
457  * then this was the last entry, so we're done. */
458  if (Regs.x.ebx == 0x00000000)
459  {
460  TRACE("End of System Memory Map! (Reset)\n");
461  break;
462  }
463  }
464  /* Check whether there would be more entries to process. */
465  if (PcBiosMapCount >= MAX_BIOS_DESCRIPTORS && Regs.x.ebx != 0x00000000)
466  {
467  ERR("PcBiosMemoryMap is already full! (PcBiosMapCount = %lu (>= %lu), PcMapCount = %lu)\n",
469  // NotWantedForPublicBuilds: ASSERTMSG("PcBiosMemoryMap is already full!\n", FALSE);
470  /* We keep retrieved entries, but ignore next entries.
471  * We assume these entries are good to use as is. If they are not, we are in trouble...
472  *
473  * FIXME: Safer = revert retrieved entries, Safest = increase MAX_BIOS_DESCRIPTORS.
474  */
475  }
476 
477  TRACE("PcMemGetBiosMemoryMap end: PcBiosMapCount = %lu\n", PcBiosMapCount);
478  return PcBiosMapCount;
479 }
ULONG PcMapCount
Definition: pcmem.c:44
NTSYSAPI VOID NTAPI RtlCopyMemory(VOID UNALIGNED *Destination, CONST VOID UNALIGNED *Source, ULONG Length)
Type
Definition: Type.h:6
ULONG ErrorLog
Definition: pcbios.h:48
#define BIOSCALLBUFFER
Definition: x86common.h:12
#define WARN(fmt,...)
Definition: debug.h:111
unsigned long eax
Definition: pcbios.h:71
DWORDREGS x
Definition: pcbios.h:140
unsigned long ebx
Definition: pcbios.h:72
#define EFLAGS_CF
Definition: ketypes.h:123
unsigned short es
Definition: pcbios.h:101
enum _TYPE_OF_MEMORY TYPE_OF_MEMORY
int __cdecl Int386(int ivec, REGS *in, REGS *out)
ULONG PFN_NUMBER
Definition: ke.h:8
#define BIOSCALLBUFSEGMENT
Definition: x86common.h:21
#define INT386_SUCCESS(regs)
Definition: pcbios.h:159
#define ASSERTMSG(msg, exp)
Definition: nt_native.h:431
#define FIXME(fmt,...)
Definition: debug.h:110
LONGLONG BaseAddress
Definition: osloader.h:33
#define ULONGLONG_ALIGN_DOWN_BY(size, align)
Definition: pcmem.c:32
_In_ HANDLE _Outptr_result_bytebuffer_ ViewSize PVOID * BaseAddress
Definition: mmfuncs.h:404
#define TRACE(s)
Definition: solgame.cpp:4
BIOS_MEMORY_MAP PcBiosMemoryMap[MAX_BIOS_DESCRIPTORS]
Definition: pcmem.c:40
uint64_t ULONGLONG
Definition: typedefs.h:65
#define BIOSCALLBUFOFFSET
Definition: x86common.h:22
#define RTL_SIZEOF_THROUGH_FIELD(type, field)
Definition: ntbasedef.h:679
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:101
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel) ?(CompletionRoutine !=NULL) :TRUE)
unsigned long eflags
Definition: pcbios.h:85
#define PAGE_SIZE
Definition: env_spec_w32.h:49
ULONG AddMemoryDescriptor(IN OUT PFREELDR_MEMORY_DESCRIPTOR List, IN ULONG MaxCount, IN PFN_NUMBER BasePage, IN PFN_NUMBER PageCount, IN TYPE_OF_MEMORY MemoryType)
Definition: meminit.c:102
#define ERR(fmt,...)
Definition: debug.h:109
#define ULONGLONG_ALIGN_UP_BY(size, align)
Definition: pcmem.c:35
FREELDR_MEMORY_DESCRIPTOR PcMemoryMap[MAX_BIOS_DESCRIPTORS+1]
Definition: pcmem.c:43
#define MAX_BIOS_DESCRIPTORS
Definition: pcmem.c:38
Definition: pcbios.h:138
unsigned long ecx
Definition: pcbios.h:73
unsigned long edx
Definition: pcbios.h:74
LONGLONG Length
Definition: osloader.h:34
struct BIOS_MEMORY_MAP * PBIOS_MEMORY_MAP
unsigned short di
Definition: pcbios.h:97
ULONG PcBiosMapCount
Definition: pcmem.c:41
WORDREGS w
Definition: pcbios.h:142

Referenced by PcMemGetMemoryMap().

◆ PcMemGetConventionalMemorySize()

static ULONG PcMemGetConventionalMemorySize ( VOID  )
static

Definition at line 152 of file pcmem.c.

153 {
154  REGS Regs;
155 
156  TRACE("PcMemGetConventionalMemorySize()\n");
157 
158  /* Int 12h
159  * BIOS - GET MEMORY SIZE
160  *
161  * Return:
162  * AX = kilobytes of contiguous memory starting at absolute address 00000h
163  *
164  * This call returns the contents of the word at 0040h:0013h;
165  * in PC and XT, this value is set from the switches on the motherboard
166  */
167  Regs.w.ax = 0;
168  Int386(0x12, &Regs, &Regs);
169 
170  TRACE("Int12h\n");
171  TRACE("AX = 0x%x\n", Regs.w.ax);
172 
173  return (ULONG)Regs.w.ax;
174 }
int __cdecl Int386(int ivec, REGS *in, REGS *out)
#define TRACE(s)
Definition: solgame.cpp:4
unsigned short ax
Definition: pcbios.h:91
unsigned int ULONG
Definition: retypes.h:1
Definition: pcbios.h:138
WORDREGS w
Definition: pcbios.h:142

Referenced by PcMemGetMemoryMap().

◆ PcMemGetMemoryMap()

PFREELDR_MEMORY_DESCRIPTOR PcMemGetMemoryMap ( ULONG MemoryMapSize)

Definition at line 543 of file pcmem.c.

544 {
545  ULONG i, EntryCount;
546  ULONG ExtendedMemorySizeAtOneMB;
547  ULONG ExtendedMemorySizeAtSixteenMB;
548  ULONG EbdaBase, EbdaSize;
549 
550  TRACE("PcMemGetMemoryMap()\n");
551 
553 
555 
556  /* If the BIOS didn't provide a memory map, synthesize one */
557  if (EntryCount == 0)
558  {
559  GetExtendedMemoryConfiguration(&ExtendedMemorySizeAtOneMB,
560  &ExtendedMemorySizeAtSixteenMB);
561 
562  /* Conventional memory */
565  0,
567  LoaderFree);
568 
569  /* Extended memory */
572  1024 * 1024 / PAGE_SIZE,
573  ExtendedMemorySizeAtOneMB * 1024 / PAGE_SIZE,
574  LoaderFree);
575 
576  if (ExtendedMemorySizeAtSixteenMB != 0)
577  {
578  /* Extended memory at 16MB */
581  0x1000000 / PAGE_SIZE,
582  ExtendedMemorySizeAtSixteenMB * 64 * 1024 / PAGE_SIZE,
583  LoaderFree);
584  }
585 
586  /* Check if we have an EBDA and get it's location */
587  if (GetEbdaLocation(&EbdaBase, &EbdaSize))
588  {
589  /* Add the descriptor */
592  (EbdaBase / PAGE_SIZE),
593  ADDRESS_AND_SIZE_TO_SPAN_PAGES(EbdaBase, EbdaSize),
595  }
596  }
597 
598  /* Setup some protected ranges */
599  SetMemory(0x000000, 0x01000, LoaderFirmwarePermanent); // Realmode IVT / BDA
600  SetMemory(0x0A0000, 0x50000, LoaderFirmwarePermanent); // Video memory
601  SetMemory(0x0F0000, 0x10000, LoaderSpecialMemory); // ROM
602  SetMemory(0xFFF000, 0x01000, LoaderSpecialMemory); // unusable memory (do we really need this?)
603 
604  /* Reserve some static ranges for freeldr */
605  ReserveMemory(0x1000, STACKLOW - 0x1000, LoaderFirmwareTemporary, "BIOS area");
608 
609  /* Default to 1 page above freeldr for the disk read buffer */
612 
613  /* Scan for free range above freeldr image */
614  for (i = 0; i < PcMapCount; i++)
615  {
616  if ((PcMemoryMap[i].BasePage > (FREELDR_BASE / PAGE_SIZE)) &&
618  {
619  /* Use this range for the disk read buffer */
620  DiskReadBuffer = (PVOID)(PcMemoryMap[i].BasePage * PAGE_SIZE);
623  break;
624  }
625  }
626 
627  TRACE("DiskReadBuffer=0x%p, DiskReadBufferSize=0x%lx\n",
629 
630  /* Now reserve the range for the disk read buffer */
634  "Disk read buffer");
635 
636  TRACE("Dumping resulting memory map:\n");
637  for (i = 0; i < PcMapCount; i++)
638  {
639  TRACE("BasePage=0x%lx, PageCount=0x%lx, Type=%s\n",
640  PcMemoryMap[i].BasePage,
641  PcMemoryMap[i].PageCount,
642  MmGetSystemMemoryMapTypeString(PcMemoryMap[i].MemoryType));
643  }
644 
645  *MemoryMapSize = PcMapCount;
646  return PcMemoryMap;
647 }
ULONG PcMapCount
Definition: pcmem.c:44
#define FREELDR_BASE
Definition: hardware.h:18
VOID SetMemory(ULONG_PTR BaseAddress, SIZE_T Size, TYPE_OF_MEMORY MemoryType)
Definition: pcmem.c:524
#define DiskReadBuffer
Definition: hardware.h:33
unsigned char * PUCHAR
Definition: retypes.h:3
TYPE_OF_MEMORY MemoryType
Definition: mm.h:38
uint32_t ULONG_PTR
Definition: typedefs.h:63
#define STACKADDR
Definition: x86common.h:16
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
#define MAX_DISKREADBUFFER_SIZE
Definition: x86common.h:30
static BOOLEAN GetEbdaLocation(PULONG BaseAddress, PULONG Size)
Definition: pcmem.c:178
void * PVOID
Definition: retypes.h:9
#define ADDRESS_AND_SIZE_TO_SPAN_PAGES(_Va, _Size)
#define STACKLOW
Definition: x86common.h:15
#define TRACE(s)
Definition: solgame.cpp:4
VOID ReserveMemory(ULONG_PTR BaseAddress, SIZE_T Size, TYPE_OF_MEMORY MemoryType, PCHAR Usage)
Definition: pcmem.c:482
static BOOLEAN GetExtendedMemoryConfiguration(ULONG *pMemoryAtOneMB, ULONG *pMemoryAtSixteenMB)
Definition: pcmem.c:56
SIZE_T DiskReadBufferSize
Definition: hwdisk.c:48
static ULONG PcMemGetBiosMemoryMap(PFREELDR_MEMORY_DESCRIPTOR MemoryMap, ULONG MaxMemoryMapSize)
Definition: pcmem.c:238
#define PAGE_SIZE
Definition: env_spec_w32.h:49
ULONG AddMemoryDescriptor(IN OUT PFREELDR_MEMORY_DESCRIPTOR List, IN ULONG MaxCount, IN PFN_NUMBER BasePage, IN PFN_NUMBER PageCount, IN TYPE_OF_MEMORY MemoryType)
Definition: meminit.c:102
FREELDR_MEMORY_DESCRIPTOR PcMemoryMap[MAX_BIOS_DESCRIPTORS+1]
Definition: pcmem.c:43
#define min(a, b)
Definition: monoChain.cc:55
static ULONG PcMemGetConventionalMemorySize(VOID)
Definition: pcmem.c:152
#define MAX_BIOS_DESCRIPTORS
Definition: pcmem.c:38
unsigned int ULONG
Definition: retypes.h:1
#define ALIGN_UP_BY(size, align)
SIZE_T FrLdrImageSize
Definition: meminit.c:35
static VOID PcMemCheckUsableMemorySize(VOID)
Definition: pcmem.c:212

Referenced by PcMachInit().

◆ ReserveMemory()

VOID ReserveMemory ( ULONG_PTR  BaseAddress,
SIZE_T  Size,
TYPE_OF_MEMORY  MemoryType,
PCHAR  Usage 
)

Definition at line 482 of file pcmem.c.

487 {
488  ULONG_PTR BasePage, PageCount;
489  ULONG i;
490 
491  BasePage = BaseAddress / PAGE_SIZE;
493 
494  for (i = 0; i < PcMapCount; i++)
495  {
496  /* Check for conflicting descriptor */
497  if ((PcMemoryMap[i].BasePage < BasePage + PageCount) &&
498  (PcMemoryMap[i].BasePage + PcMemoryMap[i].PageCount > BasePage))
499  {
500  /* Check if the memory is free */
501  if (PcMemoryMap[i].MemoryType != LoaderFree)
502  {
505  __FILE__,
506  __LINE__,
507  "Failed to reserve memory in the range 0x%Ix - 0x%Ix for %s",
508  BaseAddress,
509  Size,
510  Usage);
511  }
512  }
513  }
514 
515  /* Add the memory descriptor */
518  BasePage,
519  PageCount,
520  MemoryType);
521 }
ULONG PcMapCount
Definition: pcmem.c:44
_Must_inspect_result_ _In_ USAGE _In_ USHORT _In_ USAGE Usage
Definition: hidpi.h:382
uint32_t ULONG_PTR
Definition: typedefs.h:63
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
#define ADDRESS_AND_SIZE_TO_SPAN_PAGES(_Va, _Size)
_In_ HANDLE _Outptr_result_bytebuffer_ ViewSize PVOID * BaseAddress
Definition: mmfuncs.h:404
#define PAGE_SIZE
Definition: env_spec_w32.h:49
ULONG AddMemoryDescriptor(IN OUT PFREELDR_MEMORY_DESCRIPTOR List, IN ULONG MaxCount, IN PFN_NUMBER BasePage, IN PFN_NUMBER PageCount, IN TYPE_OF_MEMORY MemoryType)
Definition: meminit.c:102
IN PVOID IN PVOID IN USHORT IN USHORT Size
Definition: pci.h:359
VOID FrLdrBugCheckWithMessage(ULONG BugCode, PCHAR File, ULONG Line, PSTR Format,...)
Definition: entry.c:23
FREELDR_MEMORY_DESCRIPTOR PcMemoryMap[MAX_BIOS_DESCRIPTORS+1]
Definition: pcmem.c:43
#define MAX_BIOS_DESCRIPTORS
Definition: pcmem.c:38
unsigned int ULONG
Definition: retypes.h:1

Referenced by PcMemGetMemoryMap().

◆ SetMemory()

VOID SetMemory ( ULONG_PTR  BaseAddress,
SIZE_T  Size,
TYPE_OF_MEMORY  MemoryType 
)

Definition at line 524 of file pcmem.c.

528 {
529  ULONG_PTR BasePage, PageCount;
530 
531  BasePage = BaseAddress / PAGE_SIZE;
533 
534  /* Add the memory descriptor */
537  BasePage,
538  PageCount,
539  MemoryType);
540 }
ULONG PcMapCount
Definition: pcmem.c:44
uint32_t ULONG_PTR
Definition: typedefs.h:63
#define ADDRESS_AND_SIZE_TO_SPAN_PAGES(_Va, _Size)
_In_ HANDLE _Outptr_result_bytebuffer_ ViewSize PVOID * BaseAddress
Definition: mmfuncs.h:404
#define PAGE_SIZE
Definition: env_spec_w32.h:49
ULONG AddMemoryDescriptor(IN OUT PFREELDR_MEMORY_DESCRIPTOR List, IN ULONG MaxCount, IN PFN_NUMBER BasePage, IN PFN_NUMBER PageCount, IN TYPE_OF_MEMORY MemoryType)
Definition: meminit.c:102
IN PVOID IN PVOID IN USHORT IN USHORT Size
Definition: pci.h:359
FREELDR_MEMORY_DESCRIPTOR PcMemoryMap[MAX_BIOS_DESCRIPTORS+1]
Definition: pcmem.c:43
#define MAX_BIOS_DESCRIPTORS
Definition: pcmem.c:38

Referenced by PcMemGetMemoryMap().

Variable Documentation

◆ PcBiosMapCount

ULONG PcBiosMapCount

Definition at line 41 of file pcmem.c.

Referenced by DetectAcpiBios(), and PcMemGetBiosMemoryMap().

◆ PcBiosMemoryMap

Definition at line 40 of file pcmem.c.

Referenced by DetectAcpiBios(), and PcMemGetBiosMemoryMap().

◆ PcMapCount

ULONG PcMapCount

Definition at line 44 of file pcmem.c.

Referenced by PcMemGetBiosMemoryMap(), PcMemGetMemoryMap(), ReserveMemory(), and SetMemory().

◆ PcMemoryMap