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/i... ============================================================================== --- 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;