ReactOS 0.4.15-dev-7934-g1dc8d80
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 */
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 {
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}
VOID FrLdrBugCheckWithMessage(ULONG BugCode, PCHAR File, ULONG Line, PSTR Format,...)
Definition: debug.c:28
@ MEMORY_INIT_FAILURE
Definition: debug.h:143
ULONG PFN_NUMBER
Definition: ke.h:9
#define TRACE(s)
Definition: solgame.cpp:4
#define RtlMoveMemory(Destination, Source, Length)
Definition: typedefs.h:264
uint32_t ULONG
Definition: typedefs.h:59
_In_ WDFCOLLECTION _In_ ULONG Index
_Must_inspect_result_ _In_ WDFCMRESLIST List
Definition: wdfresource.h:550
int WINAPI EndPage(_In_ HDC)

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
#define FALSE
Definition: types.h:117
_In_ HANDLE _Outptr_result_bytebuffer_ ViewSize PVOID * BaseAddress
Definition: mmfuncs.h:404
#define INT386_SUCCESS(regs)
Definition: pcbios.h:179
int __cdecl Int386(int ivec, REGS *in, REGS *out)
unsigned long eax
Definition: pcbios.h:91
unsigned short es
Definition: pcbios.h:121
Definition: pcbios.h:159
DWORDREGS x
Definition: pcbios.h:160
WORDREGS w
Definition: pcbios.h:162
_Must_inspect_result_ _In_ WDFDEVICE _In_ PWDF_DEVICE_PROPERTY_DATA _In_ DEVPROPTYPE _In_ ULONG Size
Definition: wdfdevice.h:4533

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}
#define EFLAGS_CF
Definition: ketypes.h:184
#define READ_PORT_UCHAR(p)
Definition: pc98vid.h:22
#define WRITE_PORT_UCHAR(p, d)
Definition: pc98vid.h:21
unsigned char ah
Definition: pcbios.h:132
unsigned long eflags
Definition: pcbios.h:105
unsigned short cx
Definition: pcbios.h:113
unsigned short dx
Definition: pcbios.h:114
unsigned short bx
Definition: pcbios.h:112
unsigned short ax
Definition: pcbios.h:111
unsigned char * PUCHAR
Definition: typedefs.h:53
BYTEREGS b
Definition: pcbios.h:163

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!",
230 }
231}
#define FREELDR_BASE
Definition: hardware.h:18
SIZE_T FrLdrImageSize
Definition: meminit.c:35
#define PAGE_SIZE
Definition: env_spec_w32.h:49
uint16_t * PUSHORT
Definition: typedefs.h:56
uint32_t ULONG_PTR
Definition: typedefs.h:65
_Must_inspect_result_ _In_ WDFDEVICE _In_ PWDF_DEVICE_PROPERTY_DATA _In_ ULONG _Out_ PVOID _Out_ PULONG RequiredSize
Definition: wdfdevice.h:4439

Referenced by PcMemGetMemoryMap().

◆ PcMemFinalizeMemoryMap()

ULONG PcMemFinalizeMemoryMap ( PFREELDR_MEMORY_DESCRIPTOR  MemoryMap)

Definition at line 547 of file pcmem.c.

549{
550 ULONG i;
551
552 /* Reserve some static ranges for freeldr */
553 ReserveMemory(MemoryMap, 0x1000, STACKLOW - 0x1000, LoaderFirmwareTemporary, "BIOS area");
556
557 /* Default to 1 page above freeldr for the disk read buffer */
560
561 /* Scan for free range above freeldr image */
562 for (i = 0; i < PcMapCount; i++)
563 {
564 if ((MemoryMap[i].BasePage > (FREELDR_BASE / PAGE_SIZE)) &&
565 (MemoryMap[i].MemoryType == LoaderFree))
566 {
567 /* Use this range for the disk read buffer */
568 DiskReadBuffer = (PVOID)(MemoryMap[i].BasePage * PAGE_SIZE);
571 break;
572 }
573 }
574
575 TRACE("DiskReadBuffer=0x%p, DiskReadBufferSize=0x%lx\n",
577
579
580 /* Now reserve the range for the disk read buffer */
585 "Disk read buffer");
586
587 TRACE("Dumping resulting memory map:\n");
588 for (i = 0; i < PcMapCount; i++)
589 {
590 TRACE("BasePage=0x%lx, PageCount=0x%lx, Type=%s\n",
591 MemoryMap[i].BasePage,
592 MemoryMap[i].PageCount,
593 MmGetSystemMemoryMapTypeString(MemoryMap[i].MemoryType));
594 }
595 return PcMapCount;
596}
#define ALIGN_UP_BY(size, align)
BIOS_MEMORY_MAP MemoryMap[32]
Definition: loader.c:11
#define DiskReadBuffer
Definition: hardware.h:33
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
SIZE_T DiskReadBufferSize
Definition: hwdisk.c:50
#define ASSERT(a)
Definition: mode.c:44
#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:484
ULONG PcMapCount
Definition: pcmem.c:41
@ LoaderFree
Definition: arc.h:176
@ LoaderFirmwareTemporary
Definition: arc.h:179
@ LoaderLoadedProgram
Definition: arc.h:178
@ LoaderOsloaderStack
Definition: arc.h:182
void * PVOID
Definition: typedefs.h:50
#define STACKLOW
Definition: x86common.h:15
#define STACKADDR
Definition: x86common.h:16
#define MAX_DISKREADBUFFER_SIZE
Definition: x86common.h:30

Referenced by Pc98MemGetMemoryMap(), 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
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("Discarding 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("Discarding 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 /*
344 * Other deprecated ExtendedAttributes flags such as NonVolatile_Deprecated_Reserved
345 * or SlowAccess_Deprecated_Reserved are simply ignored.
346 */
347
348 /* Copy data to global buffer */
350
351 TRACE("BaseAddress: 0x%llx\n", PcBiosMemoryMap[PcBiosMapCount].BaseAddress);
352 TRACE("Length: 0x%llx\n", PcBiosMemoryMap[PcBiosMapCount].Length);
353 TRACE("Type: 0x%lx\n", PcBiosMemoryMap[PcBiosMapCount].Type);
354 TRACE("ExtendedAttributesAsULONG: 0x%08lx\n", PcBiosMemoryMap[PcBiosMapCount].ExtendedAttributesAsULONG);
355
356 if (PcBiosMemoryMap[PcBiosMapCount].ExtendedAttributes.ErrorLog == 1)
357 {
358 FIXME("EA.ErrorLog = 1. Please report this to CORE-14150. "
359 "(PcBiosMapCount = %lu, BaseAddress = 0x%llx, Length = 0x%llx, Type = 0x%lx, ExtendedAttributesAsULONG = 0x%08lx)\n",
364 PcBiosMemoryMap[PcBiosMapCount].ExtendedAttributesAsULONG);
365 // NotWantedForPublicBuilds: ASSERTMSG("EA.ErrorLog = 1. Check/Report then CONTinue.\n", FALSE);
366 }
367
369 {
370 TRACE("Discarding empty range. (would-be-PcBiosMapCount = %lu, BaseAddress = 0x%llx, Length = 0)\n",
372 goto nextRange;
373 }
374
375 /* Check if this is free memory */
377 {
378 MemoryType = LoaderFree;
379
380 /* Align up base of memory range */
381 RealBaseAddress = ULONGLONG_ALIGN_UP_BY(
383 PAGE_SIZE);
384
385 /* Calculate aligned EndAddress */
388 EndAddress = ULONGLONG_ALIGN_DOWN_BY(EndAddress, PAGE_SIZE);
389
390 /* Check if there is anything left */
391 if (EndAddress <= RealBaseAddress)
392 {
393 /* This doesn't span any page, so continue with next range */
394 TRACE("Skipping aligned range < PAGE_SIZE. (would-be-PcBiosMapCount = %lu, BaseAddress = 0x%llx, Length = 0x%llx)\n",
398 goto nextRange;
399 }
400
401 /* Calculate the length of the aligned range */
402 RealSize = EndAddress - RealBaseAddress;
403 }
404 else
405 {
407 {
408 MemoryType = LoaderFirmwarePermanent;
409 }
410 else
411 {
412 MemoryType = LoaderSpecialMemory;
413 }
414
415 /* Align down base of memory area */
416 RealBaseAddress = ULONGLONG_ALIGN_DOWN_BY(
418 PAGE_SIZE);
419
420 /* Calculate the length after aligning the base */
422 PcBiosMemoryMap[PcBiosMapCount].Length - RealBaseAddress;
423 RealSize = ULONGLONG_ALIGN_UP_BY(RealSize, PAGE_SIZE);
424 }
425
426 /* Check if we can add this descriptor */
427 if (RealSize < MM_PAGE_SIZE)
428 {
429 TRACE("Skipping aligned range < MM_PAGE_SIZE. (PcBiosMapCount = %lu, BaseAddress = 0x%llx, Length = 0x%llx)\n",
433 }
434 else if (PcMapCount >= MaxMemoryMapSize)
435 {
436 ERR("PcMemoryMap is already full! (PcBiosMapCount = %lu, PcMapCount = %lu (>= %lu))\n",
437 PcBiosMapCount, PcMapCount, MaxMemoryMapSize);
438 // NotWantedForPublicBuilds: ASSERTMSG("PcMemoryMap is already full!\n", FALSE);
439 /* We keep previous entries, and half-retrieve current/next entries.
440 * We assume all these entries are good to use as is. If they are not, we are in trouble...
441 *
442 * FIXME: Safer = revert (half-)retrieved entries, Safest = increase MaxMemoryMapSize.
443 */
444 }
445 else
446 {
447 /* Add the descriptor */
450 (PFN_NUMBER)(RealBaseAddress / MM_PAGE_SIZE),
451 (PFN_NUMBER)(RealSize / MM_PAGE_SIZE),
452 MemoryType);
453 }
454
456
457nextRange:
458 /* If the continuation value is zero,
459 * then this was the last entry, so we're done. */
460 if (Regs.x.ebx == 0x00000000)
461 {
462 TRACE("End of System Memory Map! (Reset)\n");
463 break;
464 }
465 }
466 /* Check whether there would be more entries to process. */
467 if (PcBiosMapCount >= MAX_BIOS_DESCRIPTORS && Regs.x.ebx != 0x00000000)
468 {
469 ERR("PcBiosMemoryMap is already full! (PcBiosMapCount = %lu (>= %lu), PcMapCount = %lu)\n",
471 // NotWantedForPublicBuilds: ASSERTMSG("PcBiosMemoryMap is already full!\n", FALSE);
472 /* We keep retrieved entries, but ignore next entries.
473 * We assume these entries are good to use as is. If they are not, we are in trouble...
474 *
475 * FIXME: Safer = revert retrieved entries, Safest = increase MAX_BIOS_DESCRIPTORS.
476 */
477 }
478
479 TRACE("PcMemGetBiosMemoryMap end: PcBiosMapCount = %lu\n", PcBiosMapCount);
480 return PcBiosMapCount;
481}
Type
Definition: Type.h:7
#define FIXME(fmt,...)
Definition: debug.h:111
#define WARN(fmt,...)
Definition: debug.h:112
#define ERR(fmt,...)
Definition: debug.h:110
#define ASSERTMSG(msg, exp)
Definition: nt_native.h:431
#define RTL_SIZEOF_THROUGH_FIELD(type, field)
Definition: ntbasedef.h:672
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:102
@ BiosMemoryUsable
Definition: osloader.h:22
@ BiosMemoryReserved
Definition: osloader.h:25
struct BIOS_MEMORY_MAP * PBIOS_MEMORY_MAP
#define MAX_BIOS_DESCRIPTORS
Definition: pcbios.h:12
#define ULONGLONG_ALIGN_UP_BY(size, align)
Definition: pcmem.c:34
FREELDR_MEMORY_DESCRIPTOR PcMemoryMap[MAX_BIOS_DESCRIPTORS+1]
Definition: pcmem.c:40
ULONG PcBiosMapCount
Definition: pcmem.c:38
BIOS_MEMORY_MAP PcBiosMemoryMap[MAX_BIOS_DESCRIPTORS]
Definition: pcmem.c:37
#define ULONGLONG_ALIGN_DOWN_BY(size, align)
Definition: pcmem.c:31
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
@ LoaderFirmwarePermanent
Definition: arc.h:180
@ LoaderSpecialMemory
Definition: arc.h:196
enum _TYPE_OF_MEMORY TYPE_OF_MEMORY
LONGLONG BaseAddress
Definition: osloader.h:33
LONGLONG Length
Definition: osloader.h:34
ULONG ErrorLog
Definition: pcbios.h:62
unsigned long ebx
Definition: pcbios.h:92
unsigned long edx
Definition: pcbios.h:94
unsigned long ecx
Definition: pcbios.h:93
unsigned short di
Definition: pcbios.h:117
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
uint64_t ULONGLONG
Definition: typedefs.h:67
#define BIOSCALLBUFSEGMENT
Definition: x86common.h:21
#define BIOSCALLBUFOFFSET
Definition: x86common.h:22
#define BIOSCALLBUFFER
Definition: x86common.h:12

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}

Referenced by PcMemGetMemoryMap().

◆ PcMemGetMemoryMap()

PFREELDR_MEMORY_DESCRIPTOR PcMemGetMemoryMap ( ULONG MemoryMapSize)

Definition at line 599 of file pcmem.c.

600{
601 ULONG EntryCount;
602 ULONG ExtendedMemorySizeAtOneMB;
603 ULONG ExtendedMemorySizeAtSixteenMB;
604 ULONG EbdaBase, EbdaSize;
605
606 TRACE("PcMemGetMemoryMap()\n");
607
609
611
612 /* If the BIOS didn't provide a memory map, synthesize one */
613 if (EntryCount == 0)
614 {
615 GetExtendedMemoryConfiguration(&ExtendedMemorySizeAtOneMB,
616 &ExtendedMemorySizeAtSixteenMB);
617
618 /* Conventional memory */
621 0,
623 LoaderFree);
624
625 /* Extended memory */
628 1024 * 1024 / PAGE_SIZE,
629 ExtendedMemorySizeAtOneMB * 1024 / PAGE_SIZE,
630 LoaderFree);
631
632 if (ExtendedMemorySizeAtSixteenMB != 0)
633 {
634 /* Extended memory at 16MB */
637 0x1000000 / PAGE_SIZE,
638 ExtendedMemorySizeAtSixteenMB * 64 * 1024 / PAGE_SIZE,
639 LoaderFree);
640 }
641
642 /* Check if we have an EBDA and get it's location */
643 if (GetEbdaLocation(&EbdaBase, &EbdaSize))
644 {
645 /* Add the descriptor */
648 (EbdaBase / PAGE_SIZE),
649 ADDRESS_AND_SIZE_TO_SPAN_PAGES(EbdaBase, EbdaSize),
651 }
652 }
653
654 /* Setup some protected ranges */
655 SetMemory(PcMemoryMap, 0x000000, 0x01000, LoaderFirmwarePermanent); // Realmode IVT / BDA
656 SetMemory(PcMemoryMap, 0x0A0000, 0x50000, LoaderFirmwarePermanent); // Video memory
657 SetMemory(PcMemoryMap, 0x0F0000, 0x10000, LoaderSpecialMemory); // ROM
658 SetMemory(PcMemoryMap, 0xFFF000, 0x01000, LoaderSpecialMemory); // unusable memory (do we really need this?)
659
660 *MemoryMapSize = PcMemFinalizeMemoryMap(PcMemoryMap);
661 return PcMemoryMap;
662}
ULONG PcMemFinalizeMemoryMap(PFREELDR_MEMORY_DESCRIPTOR MemoryMap)
Definition: pcmem.c:547
static VOID PcMemCheckUsableMemorySize(VOID)
Definition: pcmem.c:209
static BOOLEAN GetExtendedMemoryConfiguration(ULONG *pMemoryAtOneMB, ULONG *pMemoryAtSixteenMB)
Definition: pcmem.c:53
static ULONG PcMemGetConventionalMemorySize(VOID)
Definition: pcmem.c:149
static ULONG PcMemGetBiosMemoryMap(PFREELDR_MEMORY_DESCRIPTOR MemoryMap, ULONG MaxMemoryMapSize)
Definition: pcmem.c:235
VOID SetMemory(PFREELDR_MEMORY_DESCRIPTOR MemoryMap, ULONG_PTR BaseAddress, SIZE_T Size, TYPE_OF_MEMORY MemoryType)
Definition: pcmem.c:527
static BOOLEAN GetEbdaLocation(PULONG BaseAddress, PULONG Size)
Definition: pcmem.c:175
#define ADDRESS_AND_SIZE_TO_SPAN_PAGES(_Va, _Size)

Referenced by MachInit().

◆ ReserveMemory()

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

Definition at line 484 of file pcmem.c.

490{
491 ULONG_PTR BasePage, PageCount;
492 ULONG i;
493
494 BasePage = BaseAddress / PAGE_SIZE;
496
497 for (i = 0; i < PcMapCount; i++)
498 {
499 /* Check for conflicting descriptor */
500 if ((MemoryMap[i].BasePage < BasePage + PageCount) &&
501 (MemoryMap[i].BasePage + MemoryMap[i].PageCount > BasePage))
502 {
503 /* Check if the memory is free */
504 if (MemoryMap[i].MemoryType != LoaderFree)
505 {
508 __FILE__,
509 __LINE__,
510 "Failed to reserve memory in the range 0x%Ix - 0x%Ix for %s",
512 Size,
513 Usage);
514 }
515 }
516 }
517
518 /* Add the memory descriptor */
521 BasePage,
522 PageCount,
523 MemoryType);
524}
_Must_inspect_result_ _In_ USAGE _In_ USHORT _In_ USAGE Usage
Definition: hidpi.h:384

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 527 of file pcmem.c.

532{
533 ULONG_PTR BasePage, PageCount;
534
535 BasePage = BaseAddress / PAGE_SIZE;
537
538 /* Add the memory descriptor */
541 BasePage,
542 PageCount,
543 MemoryType);
544}

Referenced by Pc98MemGetMemoryMap(), PcMemGetMemoryMap(), and XboxMemGetMemoryMap().

Variable Documentation

◆ PcBiosMapCount

ULONG PcBiosMapCount

Definition at line 38 of file pcmem.c.

Referenced by DetectAcpiBios(), Pc98MemGetMemoryMap(), and PcMemGetBiosMemoryMap().

◆ PcBiosMemoryMap

Definition at line 37 of file pcmem.c.

Referenced by DetectAcpiBios(), Pc98MemGetMemoryMap(), and PcMemGetBiosMemoryMap().

◆ PcMapCount

ULONG PcMapCount

◆ PcMemoryMap

Definition at line 40 of file pcmem.c.

Referenced by PcMemGetBiosMemoryMap(), and PcMemGetMemoryMap().