ReactOS  0.4.14-dev-49-gfb4591c
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))
 

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 (PFREELDR_MEMORY_DESCRIPTOR MemoryMap, ULONG_PTR BaseAddress, SIZE_T Size, TYPE_OF_MEMORY MemoryType, PCHAR Usage)
 
VOID SetMemory (PFREELDR_MEMORY_DESCRIPTOR MemoryMap, ULONG_PTR BaseAddress, SIZE_T Size, TYPE_OF_MEMORY MemoryType)
 
ULONG PcMemFinalizeMemoryMap (PFREELDR_MEMORY_DESCRIPTOR MemoryMap)
 
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

◆ ULONGLONG_ALIGN_DOWN_BY

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

Definition at line 31 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 34 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 175 of file pcmem.c.

178 {
179  REGS Regs;
180 
181  TRACE("GetEbdaLocation()\n");
182 
183  /* Get the address of the Extended BIOS Data Area (EBDA).
184  * Int 15h, AH=C1h
185  * SYSTEM - RETURN EXTENDED-BIOS DATA-AREA SEGMENT ADDRESS (PS)
186  *
187  * Return:
188  * CF set on error
189  * CF clear if successful
190  * ES = segment of data area
191  */
192  Regs.x.eax = 0x0000C100;
193  Int386(0x15, &Regs, &Regs);
194 
195  /* If the function fails, there is no EBDA */
196  if (!INT386_SUCCESS(Regs))
197  {
198  return FALSE;
199  }
200 
201  /* Get Base address and (maximum) size */
202  *BaseAddress = (ULONG)Regs.w.es << 4;
203  *Size = 0xA0000 - *BaseAddress;
204  return TRUE;
205 }
#define TRUE
Definition: types.h:120
unsigned long eax
Definition: pcbios.h:79
DWORDREGS x
Definition: pcbios.h:148
unsigned short es
Definition: pcbios.h:109
int __cdecl Int386(int ivec, REGS *in, REGS *out)
#define INT386_SUCCESS(regs)
Definition: pcbios.h:167
_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:146
WORDREGS w
Definition: pcbios.h:150

Referenced by PcMemGetMemoryMap().

◆ GetExtendedMemoryConfiguration()

static BOOLEAN GetExtendedMemoryConfiguration ( ULONG pMemoryAtOneMB,
ULONG pMemoryAtSixteenMB 
)
static

Definition at line 53 of file pcmem.c.

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

Referenced by PcMemGetMemoryMap().

◆ PcMemCheckUsableMemorySize()

static VOID PcMemCheckUsableMemorySize ( VOID  )
static

Definition at line 209 of file pcmem.c.

210 {
212 
213  TRACE("PcMemCheckUsableMemorySize()\n");
214 
215  /* Make sure the usable memory is large enough. To do this we check the 16
216  bit value at address 0x413 inside the BDA, which gives us the usable size
217  in KB */
218  Size = (*(PUSHORT)(ULONG_PTR)0x413) * 1024;
220  if (Size < RequiredSize)
221  {
224  __FILE__,
225  __LINE__,
226  "The BIOS reported a usable memory range up to 0x%lx, which is too small!\n"
227  "Required size is 0x%lx\n\n"
228  "If you see this, please report to the ReactOS team!",
229  Size, RequiredSize);
230  }
231 }
#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().

◆ PcMemFinalizeMemoryMap()

ULONG PcMemFinalizeMemoryMap ( PFREELDR_MEMORY_DESCRIPTOR  MemoryMap)

Definition at line 542 of file pcmem.c.

544 {
545  ULONG i;
546 
547  /* Reserve some static ranges for freeldr */
548  ReserveMemory(MemoryMap, 0x1000, STACKLOW - 0x1000, LoaderFirmwareTemporary, "BIOS area");
551 
552  /* Default to 1 page above freeldr for the disk read buffer */
555 
556  /* Scan for free range above freeldr image */
557  for (i = 0; i < PcMapCount; i++)
558  {
559  if ((MemoryMap[i].BasePage > (FREELDR_BASE / PAGE_SIZE)) &&
560  (MemoryMap[i].MemoryType == LoaderFree))
561  {
562  /* Use this range for the disk read buffer */
563  DiskReadBuffer = (PVOID)(MemoryMap[i].BasePage * PAGE_SIZE);
564  DiskReadBufferSize = min(MemoryMap[i].PageCount * PAGE_SIZE,
566  break;
567  }
568  }
569 
570  TRACE("DiskReadBuffer=0x%p, DiskReadBufferSize=0x%lx\n",
572 
574 
575  /* Now reserve the range for the disk read buffer */
580  "Disk read buffer");
581 
582  TRACE("Dumping resulting memory map:\n");
583  for (i = 0; i < PcMapCount; i++)
584  {
585  TRACE("BasePage=0x%lx, PageCount=0x%lx, Type=%s\n",
586  MemoryMap[i].BasePage,
587  MemoryMap[i].PageCount,
588  MmGetSystemMemoryMapTypeString(MemoryMap[i].MemoryType));
589  }
590  return PcMapCount;
591 }
ULONG PcMapCount
Definition: pcmem.c:41
#define FREELDR_BASE
Definition: hardware.h:18
BIOS_MEMORY_MAP MemoryMap[32]
Definition: loader.c:11
#define DiskReadBuffer
Definition: hardware.h:33
unsigned char * PUCHAR
Definition: retypes.h:3
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
void * PVOID
Definition: retypes.h:9
#define STACKLOW
Definition: x86common.h:15
#define TRACE(s)
Definition: solgame.cpp:4
SIZE_T DiskReadBufferSize
Definition: hwdisk.c:47
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel) ?(CompletionRoutine !=NULL) :TRUE)
#define PAGE_SIZE
Definition: env_spec_w32.h:49
#define min(a, b)
Definition: monoChain.cc:55
VOID ReserveMemory(PFREELDR_MEMORY_DESCRIPTOR MemoryMap, ULONG_PTR BaseAddress, SIZE_T Size, TYPE_OF_MEMORY MemoryType, PCHAR Usage)
Definition: pcmem.c:479
unsigned int ULONG
Definition: retypes.h:1
#define ALIGN_UP_BY(size, align)
SIZE_T FrLdrImageSize
Definition: meminit.c:35

Referenced by PcMemGetMemoryMap(), and XboxMemGetMemoryMap().

◆ PcMemGetBiosMemoryMap()

static ULONG PcMemGetBiosMemoryMap ( PFREELDR_MEMORY_DESCRIPTOR  MemoryMap,
ULONG  MaxMemoryMapSize 
)
static

Definition at line 235 of file pcmem.c.

236 {
237  REGS Regs;
238  ULONGLONG RealBaseAddress, EndAddress, RealSize;
239  TYPE_OF_MEMORY MemoryType;
240 
241  ASSERT(PcBiosMapCount == 0);
242 
243  TRACE("PcMemGetBiosMemoryMap()\n");
244 
245  /* Int 15h AX=E820h
246  * Newer BIOSes - GET SYSTEM MEMORY MAP
247  *
248  * AX = E820h
249  * EAX = 0000E820h
250  * EDX = 534D4150h ('SMAP')
251  * EBX = continuation value or 00000000h to start at beginning of map
252  * ECX = size of buffer for result, in bytes (should be >= 20 bytes)
253  * ES:DI -> buffer for result
254  * Return:
255  * CF clear if successful
256  * EAX = 534D4150h ('SMAP')
257  * ES:DI buffer filled
258  * EBX = next offset from which to copy or 00000000h if all done
259  * ECX = actual length returned in bytes
260  * CF set on error
261  * AH = error code (86h)
262  */
263  Regs.x.ebx = 0x00000000;
264 
266  {
267  /* ACPI 3.0/4.0: Set Extended Attributes to enabled/valid by default, in case entry has no E.A.. */
268  ((PBIOS_MEMORY_MAP)BIOSCALLBUFFER)->ExtendedAttributesAsULONG = 0;
269  ((PBIOS_MEMORY_MAP)BIOSCALLBUFFER)->ExtendedAttributes.Enabled_Reserved = 1;
270 
271  /* Setup the registers for the BIOS call */
272  Regs.x.eax = 0x0000E820;
273  Regs.x.edx = 0x534D4150; /* ('SMAP') */
274  /* Regs.x.ebx = 0x00000001; Continuation value already set */
275  Regs.x.ecx = sizeof(BIOS_MEMORY_MAP);
276  Regs.w.es = BIOSCALLBUFSEGMENT;
277  Regs.w.di = BIOSCALLBUFOFFSET;
278  Int386(0x15, &Regs, &Regs);
279 
280  TRACE("Memory Map Entry %lu\n", PcBiosMapCount);
281  TRACE("Int15h AX=E820h\n");
282  TRACE("EAX = 0x%lx\n", Regs.x.eax);
283  TRACE("EBX = 0x%lx\n", Regs.x.ebx);
284  TRACE("ECX = %lu\n", Regs.x.ecx);
285  TRACE("CF set = %s\n", (Regs.x.eflags & EFLAGS_CF) ? "TRUE" : "FALSE");
286 
287  /* If the BIOS didn't return 'SMAP' in EAX then
288  * it doesn't support this call. */
289  if (Regs.x.eax != 0x534D4150)
290  {
291  WARN("BIOS doesn't support Int15h AX=E820h!\n");
292  break;
293  }
294 
295  /* If the carry flag is set,
296  * then this call was past the last entry, so we're done. */
297  if (!INT386_SUCCESS(Regs))
298  {
299  TRACE("End of System Memory Map! (Past last)\n");
300  break;
301  }
302 
303  if (Regs.x.ecx == 0)
304  {
305  TRACE("Discard empty entry. (would-be-PcBiosMapCount = %lu)\n",
307  goto nextRange;
308  }
309 
310  /* Extra safety: unexpected entry length.
311  * All in-between values are valid too, as x86 is little-indian
312  * and only lower byte is used per ACPI 6.2-A.
313  */
315  Regs.x.ecx > sizeof(BIOS_MEMORY_MAP))
316  {
317  ERR("Int 15h AX=E820h returned an invalid entry length! (would-be-PcBiosMapCount = %lu, Entry length = (%Iu <=) %lu (<= %Iu))\n",
319  /* Warn user, unless wrong case is "first and not too big entry", which is otherwise harmless. */
320  if (PcBiosMapCount > 0 || Regs.x.ecx > sizeof(BIOS_MEMORY_MAP))
321  {
322  ASSERTMSG("Int 15h AX=E820h returned an invalid entry length!\n", FALSE);
323  }
324  /* We keep previous entries (if any), but do not dare trying next entries.
325  * We assume these entries are good to use as is. If they are not, we are in trouble...
326  * (And don't ask what happens if BIOS actually overflowed our entry buffer...)
327  *
328  * FIXME: Safer = revert previous entries, Safest = blacklist this BIOS.
329  */
330  break;
331  }
332 
333  if (((PBIOS_MEMORY_MAP)BIOSCALLBUFFER)->ExtendedAttributes.Enabled_Reserved == 0)
334  {
335  WARN("Discard disabled/invalid entry. (would-be-PcBiosMapCount = %lu)\n",
337  /* This unlikely case was correct between ACPI 3.0 and 4.0, so assume all is fine.
338  * Unless we would be ready to drop ACPI 3.0 compatibility.
339  */
340  goto nextRange;
341  }
342 
343  /* Copy data to global buffer */
345 
346  TRACE("BaseAddress: 0x%llx\n", PcBiosMemoryMap[PcBiosMapCount].BaseAddress);
347  TRACE("Length: 0x%llx\n", PcBiosMemoryMap[PcBiosMapCount].Length);
348  TRACE("Type: 0x%lx\n", PcBiosMemoryMap[PcBiosMapCount].Type);
349  TRACE("ExtendedAttributesAsULONG: 0x%08lx\n", PcBiosMemoryMap[PcBiosMapCount].ExtendedAttributesAsULONG);
350 
351  if (PcBiosMemoryMap[PcBiosMapCount].ExtendedAttributes.ErrorLog == 1)
352  {
353  FIXME("EA.ErrorLog = 1. Please report this to CORE-14150. "
354  "(PcBiosMapCount = %lu, BaseAddress = 0x%llx, Length = 0x%llx, Type = 0x%lx, ExtendedAttributesAsULONG = 0x%08lx)\n",
359  PcBiosMemoryMap[PcBiosMapCount].ExtendedAttributesAsULONG);
360  // NotWantedForPublicBuilds: ASSERTMSG("EA.ErrorLog = 1. Check/Report then CONTinue.\n", FALSE);
361  }
362 
364  {
365  TRACE("Discard empty range. (would-be-PcBiosMapCount = %lu, BaseAddress = 0x%llx, Length = 0)\n",
367  goto nextRange;
368  }
369 
370  /* Check if this is free memory */
372  {
373  MemoryType = LoaderFree;
374 
375  /* Align up base of memory range */
376  RealBaseAddress = ULONGLONG_ALIGN_UP_BY(
378  PAGE_SIZE);
379 
380  /* Calculate aligned EndAddress */
383  EndAddress = ULONGLONG_ALIGN_DOWN_BY(EndAddress, PAGE_SIZE);
384 
385  /* Check if there is anything left */
386  if (EndAddress <= RealBaseAddress)
387  {
388  /* This doesn't span any page, so continue with next range */
389  TRACE("Skipping aligned range < PAGE_SIZE. (would-be-PcBiosMapCount = %lu, BaseAddress = 0x%llx, Length = 0x%llx)\n",
393  goto nextRange;
394  }
395 
396  /* Calculate the length of the aligned range */
397  RealSize = EndAddress - RealBaseAddress;
398  }
399  else
400  {
402  {
403  MemoryType = LoaderFirmwarePermanent;
404  }
405  else
406  {
407  MemoryType = LoaderSpecialMemory;
408  }
409 
410  /* Align down base of memory area */
411  RealBaseAddress = ULONGLONG_ALIGN_DOWN_BY(
413  PAGE_SIZE);
414 
415  /* Calculate the length after aligning the base */
417  PcBiosMemoryMap[PcBiosMapCount].Length - RealBaseAddress;
418  RealSize = ULONGLONG_ALIGN_UP_BY(RealSize, PAGE_SIZE);
419  }
420 
421  /* Check if we can add this descriptor */
422  if (RealSize < MM_PAGE_SIZE)
423  {
424  TRACE("Skipping aligned range < MM_PAGE_SIZE. (PcBiosMapCount = %lu, BaseAddress = 0x%llx, Length = 0x%llx)\n",
428  }
429  else if (PcMapCount >= MaxMemoryMapSize)
430  {
431  ERR("PcMemoryMap is already full! (PcBiosMapCount = %lu, PcMapCount = %lu (>= %lu))\n",
432  PcBiosMapCount, PcMapCount, MaxMemoryMapSize);
433  // NotWantedForPublicBuilds: ASSERTMSG("PcMemoryMap is already full!\n", FALSE);
434  /* We keep previous entries, and half-retrieve current/next entries.
435  * We assume all these entries are good to use as is. If they are not, we are in trouble...
436  *
437  * FIXME: Safer = revert (half-)retrieved entries, Safest = increase MaxMemoryMapSize.
438  */
439  }
440  else
441  {
442  /* Add the descriptor */
445  (PFN_NUMBER)(RealBaseAddress / MM_PAGE_SIZE),
446  (PFN_NUMBER)(RealSize / MM_PAGE_SIZE),
447  MemoryType);
448  }
449 
450  PcBiosMapCount++;
451 
452 nextRange:
453  /* If the continuation value is zero,
454  * then this was the last entry, so we're done. */
455  if (Regs.x.ebx == 0x00000000)
456  {
457  TRACE("End of System Memory Map! (Reset)\n");
458  break;
459  }
460  }
461  /* Check whether there would be more entries to process. */
462  if (PcBiosMapCount >= MAX_BIOS_DESCRIPTORS && Regs.x.ebx != 0x00000000)
463  {
464  ERR("PcBiosMemoryMap is already full! (PcBiosMapCount = %lu (>= %lu), PcMapCount = %lu)\n",
466  // NotWantedForPublicBuilds: ASSERTMSG("PcBiosMemoryMap is already full!\n", FALSE);
467  /* We keep retrieved entries, but ignore next entries.
468  * We assume these entries are good to use as is. If they are not, we are in trouble...
469  *
470  * FIXME: Safer = revert retrieved entries, Safest = increase MAX_BIOS_DESCRIPTORS.
471  */
472  }
473 
474  TRACE("PcMemGetBiosMemoryMap end: PcBiosMapCount = %lu\n", PcBiosMapCount);
475  return PcBiosMapCount;
476 }
ULONG PcMapCount
Definition: pcmem.c:41
NTSYSAPI VOID NTAPI RtlCopyMemory(VOID UNALIGNED *Destination, CONST VOID UNALIGNED *Source, ULONG Length)
#define MAX_BIOS_DESCRIPTORS
Definition: pcbios.h:12
Type
Definition: Type.h:6
ULONG ErrorLog
Definition: pcbios.h:56
#define BIOSCALLBUFFER
Definition: x86common.h:12
#define WARN(fmt,...)
Definition: debug.h:111
unsigned long eax
Definition: pcbios.h:79
DWORDREGS x
Definition: pcbios.h:148
unsigned long ebx
Definition: pcbios.h:80
#define EFLAGS_CF
Definition: ketypes.h:123
unsigned short es
Definition: pcbios.h:109
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:167
#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:31
_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:37
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:93
#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:34
FREELDR_MEMORY_DESCRIPTOR PcMemoryMap[MAX_BIOS_DESCRIPTORS+1]
Definition: pcmem.c:40
Definition: pcbios.h:146
unsigned long ecx
Definition: pcbios.h:81
unsigned long edx
Definition: pcbios.h:82
LONGLONG Length
Definition: osloader.h:34
struct BIOS_MEMORY_MAP * PBIOS_MEMORY_MAP
unsigned short di
Definition: pcbios.h:105
ULONG PcBiosMapCount
Definition: pcmem.c:38
WORDREGS w
Definition: pcbios.h:150

Referenced by PcMemGetMemoryMap().

◆ PcMemGetConventionalMemorySize()

static ULONG PcMemGetConventionalMemorySize ( VOID  )
static

Definition at line 149 of file pcmem.c.

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

Referenced by PcMemGetMemoryMap().

◆ PcMemGetMemoryMap()

PFREELDR_MEMORY_DESCRIPTOR PcMemGetMemoryMap ( ULONG MemoryMapSize)

Definition at line 594 of file pcmem.c.

595 {
596  ULONG EntryCount;
597  ULONG ExtendedMemorySizeAtOneMB;
598  ULONG ExtendedMemorySizeAtSixteenMB;
599  ULONG EbdaBase, EbdaSize;
600 
601  TRACE("PcMemGetMemoryMap()\n");
602 
604 
606 
607  /* If the BIOS didn't provide a memory map, synthesize one */
608  if (EntryCount == 0)
609  {
610  GetExtendedMemoryConfiguration(&ExtendedMemorySizeAtOneMB,
611  &ExtendedMemorySizeAtSixteenMB);
612 
613  /* Conventional memory */
616  0,
618  LoaderFree);
619 
620  /* Extended memory */
623  1024 * 1024 / PAGE_SIZE,
624  ExtendedMemorySizeAtOneMB * 1024 / PAGE_SIZE,
625  LoaderFree);
626 
627  if (ExtendedMemorySizeAtSixteenMB != 0)
628  {
629  /* Extended memory at 16MB */
632  0x1000000 / PAGE_SIZE,
633  ExtendedMemorySizeAtSixteenMB * 64 * 1024 / PAGE_SIZE,
634  LoaderFree);
635  }
636 
637  /* Check if we have an EBDA and get it's location */
638  if (GetEbdaLocation(&EbdaBase, &EbdaSize))
639  {
640  /* Add the descriptor */
643  (EbdaBase / PAGE_SIZE),
644  ADDRESS_AND_SIZE_TO_SPAN_PAGES(EbdaBase, EbdaSize),
646  }
647  }
648 
649  /* Setup some protected ranges */
650  SetMemory(PcMemoryMap, 0x000000, 0x01000, LoaderFirmwarePermanent); // Realmode IVT / BDA
651  SetMemory(PcMemoryMap, 0x0A0000, 0x50000, LoaderFirmwarePermanent); // Video memory
652  SetMemory(PcMemoryMap, 0x0F0000, 0x10000, LoaderSpecialMemory); // ROM
653  SetMemory(PcMemoryMap, 0xFFF000, 0x01000, LoaderSpecialMemory); // unusable memory (do we really need this?)
654 
655  *MemoryMapSize = PcMemFinalizeMemoryMap(PcMemoryMap);
656  return PcMemoryMap;
657 }
ULONG PcMapCount
Definition: pcmem.c:41
#define MAX_BIOS_DESCRIPTORS
Definition: pcbios.h:12
static BOOLEAN GetEbdaLocation(PULONG BaseAddress, PULONG Size)
Definition: pcmem.c:175
#define ADDRESS_AND_SIZE_TO_SPAN_PAGES(_Va, _Size)
#define TRACE(s)
Definition: solgame.cpp:4
static BOOLEAN GetExtendedMemoryConfiguration(ULONG *pMemoryAtOneMB, ULONG *pMemoryAtSixteenMB)
Definition: pcmem.c:53
static ULONG PcMemGetBiosMemoryMap(PFREELDR_MEMORY_DESCRIPTOR MemoryMap, ULONG MaxMemoryMapSize)
Definition: pcmem.c:235
#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:40
ULONG PcMemFinalizeMemoryMap(PFREELDR_MEMORY_DESCRIPTOR MemoryMap)
Definition: pcmem.c:542
VOID SetMemory(PFREELDR_MEMORY_DESCRIPTOR MemoryMap, ULONG_PTR BaseAddress, SIZE_T Size, TYPE_OF_MEMORY MemoryType)
Definition: pcmem.c:522
static ULONG PcMemGetConventionalMemorySize(VOID)
Definition: pcmem.c:149
unsigned int ULONG
Definition: retypes.h:1
static VOID PcMemCheckUsableMemorySize(VOID)
Definition: pcmem.c:209

Referenced by PcMachInit().

◆ ReserveMemory()

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

Definition at line 479 of file pcmem.c.

485 {
486  ULONG_PTR BasePage, PageCount;
487  ULONG i;
488 
489  BasePage = BaseAddress / PAGE_SIZE;
491 
492  for (i = 0; i < PcMapCount; i++)
493  {
494  /* Check for conflicting descriptor */
495  if ((MemoryMap[i].BasePage < BasePage + PageCount) &&
496  (MemoryMap[i].BasePage + MemoryMap[i].PageCount > BasePage))
497  {
498  /* Check if the memory is free */
499  if (MemoryMap[i].MemoryType != LoaderFree)
500  {
503  __FILE__,
504  __LINE__,
505  "Failed to reserve memory in the range 0x%Ix - 0x%Ix for %s",
506  BaseAddress,
507  Size,
508  Usage);
509  }
510  }
511  }
512 
513  /* Add the memory descriptor */
516  BasePage,
517  PageCount,
518  MemoryType);
519 }
ULONG PcMapCount
Definition: pcmem.c:41
#define MAX_BIOS_DESCRIPTORS
Definition: pcbios.h:12
BIOS_MEMORY_MAP MemoryMap[32]
Definition: loader.c:11
_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
unsigned int ULONG
Definition: retypes.h:1

Referenced by PcMemFinalizeMemoryMap(), and XboxMemGetMemoryMap().

◆ SetMemory()

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

Definition at line 522 of file pcmem.c.

527 {
528  ULONG_PTR BasePage, PageCount;
529 
530  BasePage = BaseAddress / PAGE_SIZE;
532 
533  /* Add the memory descriptor */
536  BasePage,
537  PageCount,
538  MemoryType);
539 }
ULONG PcMapCount
Definition: pcmem.c:41
#define MAX_BIOS_DESCRIPTORS
Definition: pcbios.h:12
BIOS_MEMORY_MAP MemoryMap[32]
Definition: loader.c:11
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

Referenced by PcMemGetMemoryMap(), and XboxMemGetMemoryMap().

Variable Documentation

◆ PcBiosMapCount

ULONG PcBiosMapCount

Definition at line 38 of file pcmem.c.

Referenced by DetectAcpiBios(), and PcMemGetBiosMemoryMap().

◆ PcBiosMemoryMap

Definition at line 37 of file pcmem.c.

Referenced by DetectAcpiBios(), and PcMemGetBiosMemoryMap().

◆ PcMapCount

ULONG PcMapCount

◆ PcMemoryMap

Definition at line 40 of file pcmem.c.

Referenced by PcMemGetBiosMemoryMap(), and PcMemGetMemoryMap().