Author: tkreuzer
Date: Wed Sep 21 21:48:44 2011
New Revision: 53796
URL:
http://svn.reactos.org/svn/reactos?rev=53796&view=rev
Log:
[FREELDR]
Patch by Brian Palmer:
Properly handle a memory hole below 16MB, which some machines have.
Modified:
trunk/reactos/boot/freeldr/freeldr/arch/i386/pcmem.c
Modified: trunk/reactos/boot/freeldr/freeldr/arch/i386/pcmem.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/boot/freeldr/freeldr/arch/…
==============================================================================
--- trunk/reactos/boot/freeldr/freeldr/arch/i386/pcmem.c [iso-8859-1] (original)
+++ trunk/reactos/boot/freeldr/freeldr/arch/i386/pcmem.c [iso-8859-1] Wed Sep 21 21:48:44
2011
@@ -27,95 +27,100 @@
DBG_DEFAULT_CHANNEL(MEMORY);
-static ULONG
-PcMemGetExtendedMemorySize(VOID)
-{
- REGS RegsIn;
- REGS RegsOut;
- ULONG MemorySize;
-
- TRACE("GetExtendedMemorySize()\n");
-
- /* Int 15h AX=E801h
- * Phoenix BIOS v4.0 - GET MEMORY SIZE FOR >64M CONFIGURATIONS
- *
- * AX = E801h
- * Return:
- * CF clear if successful
- * AX = extended memory between 1M and 16M, in K (max 3C00h = 15MB)
- * BX = extended memory above 16M, in 64K blocks
- * CX = configured memory 1M to 16M, in K
- * DX = configured memory above 16M, in 64K blocks
- * CF set on error
- */
- RegsIn.w.ax = 0xE801;
- Int386(0x15, &RegsIn, &RegsOut);
-
- TRACE("Int15h AX=E801h\n");
- TRACE("AX = 0x%x\n", RegsOut.w.ax);
- TRACE("BX = 0x%x\n", RegsOut.w.bx);
- TRACE("CX = 0x%x\n", RegsOut.w.cx);
- TRACE("DX = 0x%x\n", RegsOut.w.dx);
- TRACE("CF set = %s\n\n", (RegsOut.x.eflags & EFLAGS_CF) ?
"TRUE" : "FALSE");
-
- if (INT386_SUCCESS(RegsOut))
- {
- /* If AX=BX=0000h the use CX and DX */
- if (RegsOut.w.ax == 0)
- {
- /* Return extended memory size in K */
- MemorySize = RegsOut.w.dx * 64;
- MemorySize += RegsOut.w.cx;
- return MemorySize;
- }
- else
- {
- /* Return extended memory size in K */
- MemorySize = RegsOut.w.bx * 64;
- MemorySize += RegsOut.w.ax;
- return MemorySize;
- }
- }
-
- /* If we get here then Int15 Func E801h didn't work */
- /* So try Int15 Func 88h */
-
- /* Int 15h AH=88h
- * SYSTEM - GET EXTENDED MEMORY SIZE (286+)
- *
- * AH = 88h
- * Return:
- * CF clear if successful
- * AX = number of contiguous KB starting at absolute address 100000h
- * CF set on error
- * AH = status
- * 80h invalid command (PC,PCjr)
- * 86h unsupported function (XT,PS30)
- */
- RegsIn.b.ah = 0x88;
- Int386(0x15, &RegsIn, &RegsOut);
-
- TRACE("Int15h AH=88h\n");
- TRACE("AX = 0x%x\n", RegsOut.w.ax);
- TRACE("CF set = %s\n\n", (RegsOut.x.eflags & EFLAGS_CF) ?
"TRUE" : "FALSE");
-
- if (INT386_SUCCESS(RegsOut) && RegsOut.w.ax != 0)
- {
- MemorySize = RegsOut.w.ax;
- return MemorySize;
- }
-
- /* If we get here then Int15 Func 88h didn't work */
- /* So try reading the CMOS */
- WRITE_PORT_UCHAR((PUCHAR)0x70, 0x31);
- MemorySize = READ_PORT_UCHAR((PUCHAR)0x71);
- MemorySize = (MemorySize & 0xFFFF);
- MemorySize = (MemorySize << 8);
-
- TRACE("Int15h Failed\n");
- TRACE("CMOS reports: 0x%x\n", MemorySize);
-
- return MemorySize;
+static
+BOOLEAN
+GetExtendedMemoryConfiguration(ULONG* pMemoryAtOneMB /* in KB */, ULONG*
pMemoryAtSixteenMB /* in 64KB */)
+{
+ REGS RegsIn;
+ REGS RegsOut;
+
+ TRACE("GetExtendedMemoryConfiguration()\n");
+
+ *pMemoryAtOneMB = 0;
+ *pMemoryAtSixteenMB = 0;
+
+ // Int 15h AX=E801h
+ // Phoenix BIOS v4.0 - GET MEMORY SIZE FOR >64M CONFIGURATIONS
+ //
+ // AX = E801h
+ // Return:
+ // CF clear if successful
+ // AX = extended memory between 1M and 16M, in K (max 3C00h = 15MB)
+ // BX = extended memory above 16M, in 64K blocks
+ // CX = configured memory 1M to 16M, in K
+ // DX = configured memory above 16M, in 64K blocks
+ // CF set on error
+ RegsIn.w.ax = 0xE801;
+ Int386(0x15, &RegsIn, &RegsOut);
+
+ TRACE("Int15h AX=E801h\n");
+ TRACE("AX = 0x%x\n", RegsOut.w.ax);
+ TRACE("BX = 0x%x\n", RegsOut.w.bx);
+ TRACE("CX = 0x%x\n", RegsOut.w.cx);
+ TRACE("DX = 0x%x\n", RegsOut.w.dx);
+ TRACE("CF set = %s\n\n", (RegsOut.x.eflags & EFLAGS_CF) ?
"TRUE" : "FALSE");
+
+ if (INT386_SUCCESS(RegsOut))
+ {
+ // If AX=BX=0000h the use CX and DX
+ if (RegsOut.w.ax == 0)
+ {
+ // Return extended memory size in K
+ *pMemoryAtSixteenMB = RegsOut.w.dx;
+ *pMemoryAtOneMB = RegsOut.w.cx;
+ return TRUE;
+ }
+ else
+ {
+ // Return extended memory size in K
+ *pMemoryAtSixteenMB = RegsOut.w.bx;
+ *pMemoryAtOneMB = RegsOut.w.ax;
+ return TRUE;
+ }
+ }
+
+ // If we get here then Int15 Func E801h didn't work
+ // So try Int15 Func 88h
+ // Int 15h AH=88h
+ // SYSTEM - GET EXTENDED MEMORY SIZE (286+)
+ //
+ // AH = 88h
+ // Return:
+ // CF clear if successful
+ // AX = number of contiguous KB starting at absolute address 100000h
+ // CF set on error
+ // AH = status
+ // 80h invalid command (PC,PCjr)
+ // 86h unsupported function (XT,PS30)
+ RegsIn.b.ah = 0x88;
+ Int386(0x15, &RegsIn, &RegsOut);
+
+ TRACE("Int15h AH=88h\n");
+ TRACE("AX = 0x%x\n", RegsOut.w.ax);
+ TRACE("CF set = %s\n\n", (RegsOut.x.eflags & EFLAGS_CF) ?
"TRUE" : "FALSE");
+
+ if (INT386_SUCCESS(RegsOut) && RegsOut.w.ax != 0)
+ {
+ *pMemoryAtOneMB = RegsOut.w.ax;
+ return TRUE;
+ }
+
+ // If we get here then Int15 Func 88h didn't work
+ // So try reading the CMOS
+ WRITE_PORT_UCHAR((PUCHAR)0x70, 0x31);
+ *pMemoryAtOneMB = READ_PORT_UCHAR((PUCHAR)0x71);
+ *pMemoryAtOneMB = (*pMemoryAtOneMB & 0xFFFF);
+ *pMemoryAtOneMB = (*pMemoryAtOneMB << 8);
+
+ TRACE("Int15h Failed\n");
+ TRACE("CMOS reports: 0x%x\n", *pMemoryAtOneMB);
+
+ if (*pMemoryAtOneMB != 0)
+ {
+ return TRUE;
+ }
+
+ return FALSE;
}
static ULONG
@@ -228,21 +233,36 @@
PcMemGetMemoryMap(PBIOS_MEMORY_MAP BiosMemoryMap, ULONG MaxMemoryMapSize)
{
ULONG EntryCount;
+ ULONG ExtendedMemorySizeAtOneMB;
+ ULONG ExtendedMemorySizeAtSixteenMB;
EntryCount = PcMemGetBiosMemoryMap(BiosMemoryMap, MaxMemoryMapSize);
/* If the BIOS didn't provide a memory map, synthesize one */
- if (0 == EntryCount && 2 <= MaxMemoryMapSize)
- {
- /* Conventional memory */
- BiosMemoryMap[0].BaseAddress = 0;
- BiosMemoryMap[0].Length = PcMemGetConventionalMemorySize() * 1024;
- BiosMemoryMap[0].Type = BiosMemoryUsable;
- /* Extended memory */
- BiosMemoryMap[1].BaseAddress = 1024 * 1024;
- BiosMemoryMap[1].Length = PcMemGetExtendedMemorySize() * 1024;
- BiosMemoryMap[1].Type = BiosMemoryUsable;
- EntryCount = 2;
+ if (0 == EntryCount && 3 <= MaxMemoryMapSize)
+ {
+ GetExtendedMemoryConfiguration(&ExtendedMemorySizeAtOneMB,
&ExtendedMemorySizeAtSixteenMB);
+
+ /* Conventional memory */
+ BiosMemoryMap[EntryCount].BaseAddress = 0;
+ BiosMemoryMap[EntryCount].Length = PcMemGetConventionalMemorySize() * 1024;
+ BiosMemoryMap[EntryCount].Type = BiosMemoryUsable;
+ EntryCount++;
+
+ /* Extended memory at 1MB */
+ BiosMemoryMap[EntryCount].BaseAddress = 1024 * 1024;
+ BiosMemoryMap[EntryCount].Length = ExtendedMemorySizeAtOneMB * 1024;
+ BiosMemoryMap[EntryCount].Type = BiosMemoryUsable;
+ EntryCount++;
+
+ if (ExtendedMemorySizeAtSixteenMB != 0)
+ {
+ /* Extended memory at 16MB */
+ BiosMemoryMap[EntryCount].BaseAddress = 0x1000000;
+ BiosMemoryMap[EntryCount].Length = ExtendedMemorySizeAtSixteenMB * 64 * 1024;
+ BiosMemoryMap[EntryCount].Type = BiosMemoryUsable;
+ EntryCount++;
+ }
}
return EntryCount;