Author: tkreuzer
Date: Fri Sep 23 17:35:45 2011
New Revision: 53816
URL:
http://svn.reactos.org/svn/reactos?rev=53816&view=rev
Log:
[FREELDR]
Fix some bugs in the code that deals with memory descriptors:
ArcGetMemoryDescriptor was enumerating the bios generated entries first and then the
static entries. The latter were conflicting with the former and took precedence when
initializing the page lookup table. The problem was, that MmFindLocationForPageLookupTable
would use the highest range of pages available. If that range would be conflicting with a
following static descriptor, the static would have been ignored. It only worked because on
x86 the highest bios descriptor has enough free pages, before it conflicts with a static
entry (page 0xfff, marked as unusable), so that the page lookup table could be created.
MmGetAddressablePageCountIncludingHoles enumerated all memory descriptors to find
MmLowestPhysicalPage, but it was only counting FreeMemory, thus skipping all other memory
ranges. This only worked, due to the previous bug, so that the bios pages shown first took
precedence over the following static descriptors. Without the former bug
MmLowestPhysicalPage would be 0x100 which would tigger in the next bug:
MmAreMemoryPagesAvailable took the passed address range and looked up all pages in the
lookup table to see whether all are free. Now the function didn't check, whether the
passed address was below MmLowestPhysicalPage and in case it was, happily accessed the
memory below the lookup table. This would result in hal being loaded at 0x40000
overwriting the loader itself.
This is all fixe by implementing a new way of creating the memory map. First there is a
static memory map, which has enough free entries to add dynamic ranges. Then
AddMemoryDescriptor will allow you to add a new range,
while the already existing ranges will take precedence and the new ranges will be properly
split and inserted, so that the resulting map does not contain any overlapping regions and
is sorted from low to high pages. The static memory descriptor exists in the architecture
specific file.
The code that enumerates the bios information now uses this function to add the ranges on
top of the static descriptor.
More cleanup work to follow.
Modified:
trunk/reactos/boot/freeldr/freeldr/arch/arm/macharm.c
trunk/reactos/boot/freeldr/freeldr/arch/i386/pcmem.c
trunk/reactos/boot/freeldr/freeldr/arch/i386/xboxmem.c
trunk/reactos/boot/freeldr/freeldr/debug.c
trunk/reactos/boot/freeldr/freeldr/include/arch/i386/machxbox.h
trunk/reactos/boot/freeldr/freeldr/include/arch/pc/machpc.h
trunk/reactos/boot/freeldr/freeldr/include/arch/pc/x86common.h
trunk/reactos/boot/freeldr/freeldr/include/machine.h
trunk/reactos/boot/freeldr/freeldr/mm/meminit.c
Modified: trunk/reactos/boot/freeldr/freeldr/arch/arm/macharm.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/boot/freeldr/freeldr/arch/…
==============================================================================
--- trunk/reactos/boot/freeldr/freeldr/arch/arm/macharm.c [iso-8859-1] (original)
+++ trunk/reactos/boot/freeldr/freeldr/arch/arm/macharm.c [iso-8859-1] Fri Sep 23 17:35:45
2011
@@ -143,12 +143,25 @@
return RootNode;
}
-PBIOS_MEMORY_MAP
-ArmMemGetMemoryMap(OUT PULONG MaxMemoryMapSize)
-{
+MEMORY_DESCRIPTOR ArmMemoryMap[32];
+
+PMEMORY_DESCRIPTOR
+ArmMemGetMemoryMap(OUT ULONG *MemoryMapSize)
+{
+ ASSERT(ArmBoardBlock->MemoryMapEntryCount <= 32);
+
/* Return whatever the board returned to us (CS0 Base + Size and FLASH0) */
- *MaxMemoryMapSize = ArmBoardBlock->MemoryMapEntryCount;
- return ArmBoardBlock->MemoryMap;
+ for (i = 0; i < ArmBoardBlock->MemoryMapEntryCount; i++)
+ {
+ ArmMemoryMap[i].BasePage = ArmBoardBlock->MemoryMap[i].BaseAddress /
PAGE_SIZE;
+ ArmMemoryMap[i].PageCount = ArmBoardBlock->MemoryMap[i].Length / PAGE_SIZE;
+ if (ArmBoardBlock->MemoryMap[i].Type == BiosMemoryUsable)
+ ArmMemoryMap[i].MemoryType = MemoryFree;
+ else
+ ArmMemoryMap[i].MemoryType = MemoryFirmwarePermanent;
+ }
+
+ return ArmBoardBlock->MemoryMapEntryCount;
}
VOID
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] Fri Sep 23 17:35:45
2011
@@ -21,6 +21,7 @@
*/
#include <freeldr.h>
+#include <arch/pc/x86common.h>
#define NDEBUG
#include <debug.h>
@@ -28,9 +29,43 @@
DBG_DEFAULT_CHANNEL(MEMORY);
#define MAX_BIOS_DESCRIPTORS 32
+#define FREELDR_BASE_PAGE (FREELDR_BASE / PAGE_SIZE)
+#define FILEBUF_BASE_PAGE (FILESYSBUFFER / PAGE_SIZE)
+#define DISKBUF_BASE_PAGE (DISKREADBUFFER / PAGE_SIZE)
+#define STACK_BASE_PAGE (DISKBUF_BASE_PAGE + 1)
+#define STACK_END_PAGE (STACK32ADDR / PAGE_SIZE)
+#define BIOSBUF_BASE_PAGE (BIOSCALLBUFFER / PAGE_SIZE)
+
+#define FREELDR_PAGE_COUNT (FILEBUF_BASE_PAGE - FREELDR_BASE_PAGE)
+#define FILEBUF_PAGE_COUNT (DISKBUF_BASE_PAGE - FILEBUF_BASE_PAGE)
+#define DISKBUF_PAGE_COUNT (1)
+#define STACK_PAGE_COUNT (STACK_END_PAGE - STACK_BASE_PAGE)
+#define BIOSBUF_PAGE_COUNT (0xA0 - BIOSBUF_BASE_PAGE)
BIOS_MEMORY_MAP PcBiosMemoryMap[MAX_BIOS_DESCRIPTORS];
ULONG PcBiosMapCount;
+
+MEMORY_DESCRIPTOR PcMemoryMap[MAX_BIOS_DESCRIPTORS + 1] =
+{
+ { MemoryFirmwarePermanent, 0x00, 1 }, // realmode int vectors
+ { MemoryFirmwareTemporary, 0x01, FREELDR_BASE_PAGE - 1 }, // freeldr stack
+ cmdline
+ { MemoryLoadedProgram, FREELDR_BASE_PAGE, FREELDR_PAGE_COUNT }, // freeldr image
+ { MemoryFirmwareTemporary, FILEBUF_BASE_PAGE, FILEBUF_PAGE_COUNT }, // File system read
buffer. FILESYSBUFFER
+ { MemoryFirmwareTemporary, DISKBUF_BASE_PAGE, DISKBUF_PAGE_COUNT }, // Disk read buffer
for int 13h. DISKREADBUFFER
+ { MemorySpecialMemory, STACK_BASE_PAGE, STACK_PAGE_COUNT }, // prot mode stack.
+ { MemoryFirmwareTemporary, BIOSBUF_BASE_PAGE, BIOSBUF_PAGE_COUNT }, // BIOSCALLBUFFER
+ { MemoryFirmwarePermanent, 0xA0, 0x60 }, // ROM / Video
+ { MemorySpecialMemory, 0xFFF, 1 }, // unusable memory
+ { MemorySpecialMemory, MAXULONG_PTR, 0 }, // end of map
+};
+
+ULONG
+AddMemoryDescriptor(
+ IN OUT PMEMORY_DESCRIPTOR List,
+ IN ULONG MaxCount,
+ IN PFN_NUMBER BasePage,
+ IN PFN_NUMBER PageCount,
+ IN MEMORY_TYPE MemoryType);
static
BOOLEAN
@@ -153,11 +188,14 @@
return (ULONG)Regs.w.ax;
}
-static ULONG
-PcMemGetBiosMemoryMap(PBIOS_MEMORY_MAP BiosMemoryMap, ULONG MaxMemoryMapSize)
+static
+ULONG
+PcMemGetBiosMemoryMap(PMEMORY_DESCRIPTOR MemoryMap, ULONG MaxMemoryMapSize)
{
REGS Regs;
- ULONG MapCount;
+ ULONG MapCount = 0;
+ ULONGLONG RealBaseAddress, RealSize;
+ ASSERT(PcBiosMapCount == 0);
TRACE("GetBiosMemoryMap()\n");
@@ -181,7 +219,7 @@
*/
Regs.x.ebx = 0x00000000;
- for (MapCount = 0; MapCount < MaxMemoryMapSize; MapCount++)
+ while (PcBiosMapCount < MAX_BIOS_DESCRIPTORS)
{
/* Setup the registers for the BIOS call */
Regs.x.eax = 0x0000E820;
@@ -192,7 +230,7 @@
Regs.w.di = BIOSCALLBUFOFFSET;
Int386(0x15, &Regs, &Regs);
- TRACE("Memory Map Entry %d\n", MapCount);
+ TRACE("Memory Map Entry %d\n", PcBiosMapCount);
TRACE("Int15h AX=E820h\n");
TRACE("EAX = 0x%x\n", Regs.x.eax);
TRACE("EBX = 0x%x\n", Regs.x.ebx);
@@ -206,14 +244,39 @@
break;
}
- /* Copy data to caller's buffer */
- RtlCopyMemory(&BiosMemoryMap[MapCount], (PVOID)BIOSCALLBUFFER, Regs.x.ecx);
-
- TRACE("BaseAddress: 0x%p\n",
(PVOID)(ULONG_PTR)BiosMemoryMap[MapCount].BaseAddress);
- TRACE("Length: 0x%p\n",
(PVOID)(ULONG_PTR)BiosMemoryMap[MapCount].Length);
- TRACE("Type: 0x%x\n", BiosMemoryMap[MapCount].Type);
- TRACE("Reserved: 0x%x\n", BiosMemoryMap[MapCount].Reserved);
+ /* Copy data to global buffer */
+ RtlCopyMemory(&PcBiosMemoryMap[PcBiosMapCount], (PVOID)BIOSCALLBUFFER,
Regs.x.ecx);
+
+ TRACE("BaseAddress: 0x%p\n",
(PVOID)(ULONG_PTR)PcBiosMemoryMap[PcBiosMapCount].BaseAddress);
+ TRACE("Length: 0x%p\n",
(PVOID)(ULONG_PTR)PcBiosMemoryMap[PcBiosMapCount].Length);
+ TRACE("Type: 0x%x\n", PcBiosMemoryMap[PcBiosMapCount].Type);
+ TRACE("Reserved: 0x%x\n", PcBiosMemoryMap[PcBiosMapCount].Reserved);
TRACE("\n");
+
+ /* Align up base of memory area */
+ RealBaseAddress = ROUND_UP(PcBiosMemoryMap[PcBiosMapCount].BaseAddress,
MM_PAGE_SIZE);
+ RealSize = PcBiosMemoryMap[PcBiosMapCount].Length -
+ (RealBaseAddress - PcBiosMemoryMap[PcBiosMapCount].BaseAddress);
+
+ /* Check if we can add this descriptor */
+ if ((RealSize >= MM_PAGE_SIZE) && (MapCount < MaxMemoryMapSize))
+ {
+ MEMORY_TYPE MemoryType;
+
+ if (PcBiosMemoryMap[PcBiosMapCount].Type == BiosMemoryUsable)
+ MemoryType = MemoryFree;
+ else
+ MemoryType = MemoryFirmwarePermanent;
+
+ /* Add the descriptor */
+ MapCount = AddMemoryDescriptor(PcMemoryMap,
+ MAX_BIOS_DESCRIPTORS,
+ RealBaseAddress / MM_PAGE_SIZE,
+ RealSize / MM_PAGE_SIZE,
+ MemoryType);
+ }
+
+ PcBiosMapCount++;
/* If the continuation value is zero or the
* carry flag is set then this was
@@ -229,46 +292,59 @@
return MapCount;
}
-PBIOS_MEMORY_MAP
+
+PMEMORY_DESCRIPTOR
PcMemGetMemoryMap(ULONG *MemoryMapSize)
{
- ULONG EntryCount;
+ ULONG i, EntryCount;
ULONG ExtendedMemorySizeAtOneMB;
ULONG ExtendedMemorySizeAtSixteenMB;
- EntryCount = PcMemGetBiosMemoryMap(PcBiosMemoryMap, MAX_BIOS_DESCRIPTORS);
- PcBiosMapCount = EntryCount;
+ EntryCount = PcMemGetBiosMemoryMap(PcMemoryMap, MAX_BIOS_DESCRIPTORS);
/* If the BIOS didn't provide a memory map, synthesize one */
if (0 == EntryCount)
{
GetExtendedMemoryConfiguration(&ExtendedMemorySizeAtOneMB,
&ExtendedMemorySizeAtSixteenMB);
- /* Conventional memory */
- PcBiosMemoryMap[EntryCount].BaseAddress = 0;
- PcBiosMemoryMap[EntryCount].Length = PcMemGetConventionalMemorySize() * 1024;
- PcBiosMemoryMap[EntryCount].Type = BiosMemoryUsable;
- EntryCount++;
-
- /* Extended memory at 1MB */
- PcBiosMemoryMap[EntryCount].BaseAddress = 1024 * 1024;
- PcBiosMemoryMap[EntryCount].Length = ExtendedMemorySizeAtOneMB * 1024;
- PcBiosMemoryMap[EntryCount].Type = BiosMemoryUsable;
+ /* Conventional memory */
+ AddMemoryDescriptor(PcMemoryMap,
+ MAX_BIOS_DESCRIPTORS,
+ 0,
+ PcMemGetConventionalMemorySize() * 1024 / PAGE_SIZE,
+ MemoryFree);
+
+ /* Extended memory */
+ EntryCount = AddMemoryDescriptor(PcMemoryMap,
+ MAX_BIOS_DESCRIPTORS,
+ 1024 * 1024 / PAGE_SIZE,
+ ExtendedMemorySizeAtOneMB * 1024 / PAGE_SIZE,
+ MemoryFree);
EntryCount++;
if (ExtendedMemorySizeAtSixteenMB != 0)
{
/* Extended memory at 16MB */
- PcBiosMemoryMap[EntryCount].BaseAddress = 0x1000000;
- PcBiosMemoryMap[EntryCount].Length = ExtendedMemorySizeAtSixteenMB * 64 * 1024;
- PcBiosMemoryMap[EntryCount].Type = BiosMemoryUsable;
- EntryCount++;
+ EntryCount = AddMemoryDescriptor(PcMemoryMap,
+ MAX_BIOS_DESCRIPTORS,
+ 0x1000000 / PAGE_SIZE,
+ ExtendedMemorySizeAtSixteenMB * 64 * 1024 / PAGE_SIZE,
+ MemoryFree);
}
}
+ TRACE("Dumping resulting memory map:\n");
+ for (i = 0; i < EntryCount; i++)
+ {
+ TRACE("BasePage=0x%lx, PageCount=0x%lx, Type=%s\n",
+ PcMemoryMap[i].BasePage,
+ PcMemoryMap[i].PageCount,
+ MmGetSystemMemoryMapTypeString(PcMemoryMap[i].MemoryType));
+ }
+
*MemoryMapSize = EntryCount;
- return PcBiosMemoryMap;
+ return PcMemoryMap;
}
/* EOF */
Modified: trunk/reactos/boot/freeldr/freeldr/arch/i386/xboxmem.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/boot/freeldr/freeldr/arch/…
==============================================================================
--- trunk/reactos/boot/freeldr/freeldr/arch/i386/xboxmem.c [iso-8859-1] (original)
+++ trunk/reactos/boot/freeldr/freeldr/arch/i386/xboxmem.c [iso-8859-1] Fri Sep 23
17:35:45 2011
@@ -75,21 +75,21 @@
AvailableMemoryMb = InstalledMemoryMb;
}
-BIOS_MEMORY_MAP BiosMemoryMap[2];
+MEMORY_DESCRIPTOR BiosMemoryMap[2];
-PBIOS_MEMORY_MAP
+PMEMORY_DESCRIPTOR
XboxMemGetMemoryMap(ULONG *MemoryMapSize)
{
/* Synthesize memory map */
/* Available RAM block */
- BiosMemoryMap[0].BaseAddress = 0;
- BiosMemoryMap[0].Length = AvailableMemoryMb * 1024 * 1024;
- BiosMemoryMap[0].Type = BiosMemoryUsable;
+ BiosMemoryMap[0].BasePage = 0;
+ BiosMemoryMap[0].PageCount = AvailableMemoryMb * 1024 * 1024 / MM_PAGE_SIZE;
+ BiosMemoryMap[0].MemoryType = MemoryFree;
/* Video memory */
- BiosMemoryMap[1].BaseAddress = AvailableMemoryMb * 1024 * 1024;
- BiosMemoryMap[1].Length = (InstalledMemoryMb - AvailableMemoryMb) * 1024 * 1024;
- BiosMemoryMap[1].Type = BiosMemoryReserved;
+ BiosMemoryMap[1].BasePage = AvailableMemoryMb * 1024 * 1024 / MM_PAGE_SIZE;
+ BiosMemoryMap[1].PageCount = (InstalledMemoryMb - AvailableMemoryMb) * 1024 * 1024
/ MM_PAGE_SIZE;
+ BiosMemoryMap[1].MemoryType = MemoryFirmwarePermanent;
*MemoryMapSize = 2;
return BiosMemoryMap;
Modified: trunk/reactos/boot/freeldr/freeldr/debug.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/boot/freeldr/freeldr/debug…
==============================================================================
--- trunk/reactos/boot/freeldr/freeldr/debug.c [iso-8859-1] (original)
+++ trunk/reactos/boot/freeldr/freeldr/debug.c [iso-8859-1] Fri Sep 23 17:35:45 2011
@@ -26,7 +26,7 @@
//#define DEBUG_ALL
//#define DEBUG_INIFILE
//#define DEBUG_REACTOS
-//#define DEBUG_CUSTOM
+#define DEBUG_CUSTOM
#define DEBUG_NONE
#if defined (DEBUG_ALL)
@@ -38,7 +38,7 @@
#elif defined (DEBUG_REACTOS)
ULONG DebugPrintMask = DPRINT_REACTOS | DPRINT_REGISTRY;
#elif defined (DEBUG_CUSTOM)
-ULONG DebugPrintMask = DPRINT_WARNING | DPRINT_WINDOWS;
+ULONG DebugPrintMask = DPRINT_WARNING | DPRINT_MEMORY;
#else //#elif defined (DEBUG_NONE)
ULONG DebugPrintMask = 0;
#endif
Modified: trunk/reactos/boot/freeldr/freeldr/include/arch/i386/machxbox.h
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/boot/freeldr/freeldr/inclu…
==============================================================================
--- trunk/reactos/boot/freeldr/freeldr/include/arch/i386/machxbox.h [iso-8859-1]
(original)
+++ trunk/reactos/boot/freeldr/freeldr/include/arch/i386/machxbox.h [iso-8859-1] Fri Sep
23 17:35:45 2011
@@ -49,7 +49,7 @@
VOID XboxMemInit(VOID);
PVOID XboxMemReserveMemory(ULONG MbToReserve);
-PBIOS_MEMORY_MAP XboxMemGetMemoryMap(ULONG *MemoryMapSize);
+PMEMORY_DESCRIPTOR XboxMemGetMemoryMap(ULONG *MemoryMapSize);
BOOLEAN XboxDiskReadLogicalSectors(UCHAR DriveNumber, ULONGLONG SectorNumber, ULONG
SectorCount, PVOID Buffer);
BOOLEAN XboxDiskGetPartitionEntry(UCHAR DriveNumber, ULONG PartitionNumber,
PPARTITION_TABLE_ENTRY PartitionTableEntry);
Modified: trunk/reactos/boot/freeldr/freeldr/include/arch/pc/machpc.h
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/boot/freeldr/freeldr/inclu…
==============================================================================
--- trunk/reactos/boot/freeldr/freeldr/include/arch/pc/machpc.h [iso-8859-1] (original)
+++ trunk/reactos/boot/freeldr/freeldr/include/arch/pc/machpc.h [iso-8859-1] Fri Sep 23
17:35:45 2011
@@ -46,7 +46,7 @@
VOID PcVideoPrepareForReactOS(IN BOOLEAN Setup);
VOID PcPrepareForReactOS(IN BOOLEAN Setup);
-PBIOS_MEMORY_MAP PcMemGetMemoryMap(ULONG *MemoryMapSize);
+PMEMORY_DESCRIPTOR PcMemGetMemoryMap(ULONG *MemoryMapSize);
BOOLEAN PcDiskGetBootPath(char *BootPath, unsigned Size);
BOOLEAN PcDiskReadLogicalSectors(UCHAR DriveNumber, ULONGLONG SectorNumber, ULONG
SectorCount, PVOID Buffer);
Modified: trunk/reactos/boot/freeldr/freeldr/include/arch/pc/x86common.h
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/boot/freeldr/freeldr/inclu…
==============================================================================
--- trunk/reactos/boot/freeldr/freeldr/include/arch/pc/x86common.h [iso-8859-1]
(original)
+++ trunk/reactos/boot/freeldr/freeldr/include/arch/pc/x86common.h [iso-8859-1] Fri Sep 23
17:35:45 2011
@@ -13,11 +13,11 @@
#define BSS_START HEX(6F00)
#define FREELDR_BASE HEX(F800)
#define FREELDR_PE_BASE HEX(10000)
+#define FILESYSBUFFER HEX(80000) /* Buffer to store file system data (e.g. cluster
buffer for FAT) */
+#define DISKREADBUFFER HEX(90000) /* Buffer to store data read in from the disk via
the BIOS */
#define STACK32ADDR HEX(98000) /* The 32-bit stack top will be at 9000:8000, or
0xA8000 */
#define STACK64ADDR HEX(98000) /* The 64-bit stack top will be at 98000 */
#define BIOSCALLBUFFER HEX(98000) /* Buffer to store temporary data for any Int386()
call */
-#define FILESYSBUFFER HEX(80000) /* Buffer to store file system data (e.g. cluster
buffer for FAT) */
-#define DISKREADBUFFER HEX(90000) /* Buffer to store data read in from the disk via
the BIOS */
#define DISKREADBUFFER_SIZE 512
#define BIOSCALLBUFSEGMENT (BIOSCALLBUFFER/16) /* Buffer to store temporary data for any
Int386() call */
Modified: trunk/reactos/boot/freeldr/freeldr/include/machine.h
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/boot/freeldr/freeldr/inclu…
==============================================================================
--- trunk/reactos/boot/freeldr/freeldr/include/machine.h [iso-8859-1] (original)
+++ trunk/reactos/boot/freeldr/freeldr/include/machine.h [iso-8859-1] Fri Sep 23 17:35:45
2011
@@ -1,5 +1,4 @@
-/* $Id$
- *
+/*
* FreeLoader
*
* This program is free software; you can redistribute it and/or modify
@@ -59,7 +58,7 @@
VOID (*PrepareForReactOS)(IN BOOLEAN Setup);
MEMORY_DESCRIPTOR* (*GetMemoryDescriptor)(MEMORY_DESCRIPTOR* Current);
- PBIOS_MEMORY_MAP (*GetMemoryMap)(PULONG MemoryMapSize);
+ PMEMORY_DESCRIPTOR (*GetMemoryMap)(PULONG MaxMemoryMapSize);
BOOLEAN (*DiskGetBootPath)(char *BootPath, unsigned Size);
BOOLEAN (*DiskReadLogicalSectors)(UCHAR DriveNumber, ULONGLONG SectorNumber, ULONG
SectorCount, PVOID Buffer);
Modified: trunk/reactos/boot/freeldr/freeldr/mm/meminit.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/boot/freeldr/freeldr/mm/me…
==============================================================================
--- trunk/reactos/boot/freeldr/freeldr/mm/meminit.c [iso-8859-1] (original)
+++ trunk/reactos/boot/freeldr/freeldr/mm/meminit.c [iso-8859-1] Fri Sep 23 17:35:45 2011
@@ -53,211 +53,106 @@
ULONG MmLowestPhysicalPage = 0xFFFFFFFF;
ULONG MmHighestPhysicalPage = 0;
+PMEMORY_DESCRIPTOR BiosMemoryMap;
+ULONG BiosMemoryMapEntryCount;
+
extern ULONG_PTR MmHeapPointer;
extern ULONG_PTR MmHeapStart;
-typedef struct
-{
- MEMORY_DESCRIPTOR m;
- ULONG Index;
- BOOLEAN GeneratedDescriptor;
-} MEMORY_DESCRIPTOR_INT;
-static const MEMORY_DESCRIPTOR_INT MemoryDescriptors[] =
-{
-#if defined (__i386__) || defined (_M_AMD64)
- { { MemoryFirmwarePermanent, 0x00, 1 }, 0, }, // realmode int vectors
- { { MemoryFirmwareTemporary, 0x01, 7 }, 1, }, // freeldr stack + cmdline
- { { MemoryLoadedProgram, 0x08, 0x70 }, 2, }, // freeldr image (roughly max. 0x64
pages)
- { { MemorySpecialMemory, 0x78, 8 }, 3, }, // prot mode stack. BIOSCALLBUFFER
- { { MemoryFirmwareTemporary, 0x80, 0x10 }, 4, }, // File system read buffer.
FILESYSBUFFER
- { { MemoryFirmwareTemporary, 0x90, 0x10 }, 5, }, // Disk read buffer for int 13h.
DISKREADBUFFER
- { { MemoryFirmwarePermanent, 0xA0, 0x60 }, 6, }, // ROM / Video
- { { MemorySpecialMemory, 0xFFF, 1 }, 7, }, // unusable memory
-#elif __arm__ // This needs to be done per-platform specific way
-
-#endif
-};
-
-static
-VOID MmFixupSystemMemoryMap(PBIOS_MEMORY_MAP BiosMemoryMap, ULONG* MapCount)
-{
- int Index;
- int Index2;
- ULONGLONG BaseAddressOffset;
-
- // Loop through each entry in the array
- for (Index=0; Index<*MapCount; Index++)
- {
- // Correct all the addresses to be aligned on page boundaries
- BaseAddressOffset = ROUND_UP(BiosMemoryMap[Index].BaseAddress, MM_PAGE_SIZE) -
BiosMemoryMap[Index].BaseAddress;
- BiosMemoryMap[Index].BaseAddress += BaseAddressOffset;
- if (BiosMemoryMap[Index].Length < BaseAddressOffset)
- {
- BiosMemoryMap[Index].Length = 0;
- }
- else
- {
- BiosMemoryMap[Index].Length -= BaseAddressOffset;
- }
- BiosMemoryMap[Index].Length = ROUND_DOWN(BiosMemoryMap[Index].Length, MM_PAGE_SIZE);
-
- // If the entry type isn't usable then remove
- // it from the memory map (this will help reduce
- // the size of our lookup table)
- // If the length is less than a full page then
- // get rid of it also.
- if (BiosMemoryMap[Index].Type != BiosMemoryUsable ||
- BiosMemoryMap[Index].Length < MM_PAGE_SIZE)
- {
- // Slide every entry after this down one
- for (Index2=Index; Index2<(*MapCount - 1); Index2++)
- {
- BiosMemoryMap[Index2] = BiosMemoryMap[Index2 + 1];
- }
- (*MapCount)--;
- Index--;
- }
- }
+ULONG
+AddMemoryDescriptor(
+ IN OUT PMEMORY_DESCRIPTOR List,
+ IN ULONG MaxCount,
+ IN PFN_NUMBER BasePage,
+ IN PFN_NUMBER PageCount,
+ IN MEMORY_TYPE MemoryType)
+{
+ ULONG i, c;
+ PFN_NUMBER NextBase;
+ TRACE("AddMemoryDescriptor(0x%lx-0x%lx [0x%lx pages])\n",
+ BasePage, BasePage + PageCount, PageCount);
+
+ /* Scan through all existing descriptors */
+ for (i = 0, c = 0; (c < MaxCount) && (List[c].PageCount != 0); c++)
+ {
+ /* Count entries completely below the new range */
+ if (List[i].BasePage + List[i].PageCount <= BasePage) i++;
+ }
+
+ /* Check if the list is full */
+ if (c >= MaxCount) return c;
+
+ /* Is there an existing descriptor starting before the new range */
+ while ((i < c) && (List[i].BasePage <= BasePage))
+ {
+ /* The end of the existing one is the minimum for the new range */
+ NextBase = List[i].BasePage + List[i].PageCount;
+
+ /* Bail out, if everything is trimmed away */
+ if ((BasePage + PageCount) <= NextBase) return c;
+
+ /* Trim the naew range at the lower end */
+ PageCount -= (NextBase - BasePage);
+ BasePage = NextBase;
+
+ /* Go to the next entry and repeat */
+ i++;
+ }
+
+ ASSERT(PageCount > 0);
+
+ /* Are there still entries above? */
+ if (i < c)
+ {
+ /* Shift the following entries one up */
+ RtlMoveMemory(&List[i+1], &List[i], (c - i) * sizeof(List[0]));
+
+ /* Insert the new range */
+ List[i].BasePage = BasePage;
+ List[i].PageCount = min(PageCount, List[i+1].BasePage - BasePage);
+ List[i].MemoryType = MemoryType;
+ c++;
+
+ TRACE("Inserting at i=%ld: (0x%lx:0x%lx)\n",
+ i, List[i].BasePage, List[i].PageCount);
+
+ /* Check if the range was trimmed */
+ if (PageCount > List[i].PageCount)
+ {
+ /* Recursively process the trimmed part */
+ c = AddMemoryDescriptor(List,
+ MaxCount,
+ BasePage + List[i].PageCount,
+ PageCount - List[i].PageCount,
+ MemoryType);
+ }
+ }
+ else
+ {
+ /* We can simply add the range here */
+ TRACE("Adding i=%ld: (0x%lx:0x%lx)\n", i, BasePage, PageCount);
+ List[i].BasePage = BasePage;
+ List[i].PageCount = PageCount;
+ List[i].MemoryType = MemoryType;
+ c++;
+ }
+
+ /* Return the new count */
+ return c;
}
const MEMORY_DESCRIPTOR*
ArcGetMemoryDescriptor(const MEMORY_DESCRIPTOR* Current)
{
- MEMORY_DESCRIPTOR_INT* CurrentDescriptor;
- PBIOS_MEMORY_MAP BiosMemoryMap;
- static ULONG BiosMemoryMapEntryCount;
- static MEMORY_DESCRIPTOR_INT BiosMemoryDescriptors[32];
- static BOOLEAN MemoryMapInitialized = FALSE;
- ULONG i, j;
-
- //
- // Check if it is the first time we're called
- //
- if (!MemoryMapInitialized)
- {
- //
- // Get the machine generated memory map
- //
- BiosMemoryMap = MachVtbl.GetMemoryMap(&BiosMemoryMapEntryCount);
-
- //
- // Fix entries that are not page aligned
- //
- MmFixupSystemMemoryMap(BiosMemoryMap, &BiosMemoryMapEntryCount);
-
- //
- // Copy the entries to our structure
- //
- for (i = 0, j = 0; i < BiosMemoryMapEntryCount; i++)
- {
- //
- // Is it suitable memory?
- //
- if (BiosMemoryMap[i].Type != BiosMemoryUsable)
- {
- //
- // No. Process next descriptor
- //
- continue;
- }
-
- //
- // Copy this memory descriptor
- //
- BiosMemoryDescriptors[j].m.MemoryType = MemoryFree;
- BiosMemoryDescriptors[j].m.BasePage = (ULONG)(BiosMemoryMap[i].BaseAddress /
MM_PAGE_SIZE);
- BiosMemoryDescriptors[j].m.PageCount = (ULONG)(BiosMemoryMap[i].Length /
MM_PAGE_SIZE);
- BiosMemoryDescriptors[j].Index = j;
- BiosMemoryDescriptors[j].GeneratedDescriptor = TRUE;
- j++;
- }
-
- //
- // Remember how much descriptors we found
- //
- BiosMemoryMapEntryCount = j;
-
- //
- // Mark memory map as already retrieved and initialized
- //
- MemoryMapInitialized = TRUE;
- }
-
- CurrentDescriptor = CONTAINING_RECORD(Current, MEMORY_DESCRIPTOR_INT, m);
-
if (Current == NULL)
{
- //
- // First descriptor requested
- //
- if (BiosMemoryMapEntryCount > 0)
- {
- //
- // Return first generated memory descriptor
- //
- return &BiosMemoryDescriptors[0].m;
- }
- else if (sizeof(MemoryDescriptors) > 0)
- {
- //
- // Return first fixed memory descriptor
- //
- return &MemoryDescriptors[0].m;
- }
- else
- {
- //
- // Strange case, we have no memory descriptor
- //
- return NULL;
- }
- }
- else if (CurrentDescriptor->GeneratedDescriptor)
- {
- //
- // Current entry is a generated descriptor
- //
- if (CurrentDescriptor->Index + 1 < BiosMemoryMapEntryCount)
- {
- //
- // Return next generated descriptor
- //
- return &BiosMemoryDescriptors[CurrentDescriptor->Index + 1].m;
- }
- else if (sizeof(MemoryDescriptors) > 0)
- {
- //
- // Return first fixed memory descriptor
- //
- return &MemoryDescriptors[0].m;
- }
- else
- {
- //
- // No fixed memory descriptor; end of memory map
- //
- return NULL;
- }
+ return BiosMemoryMap;
}
else
{
- //
- // Current entry is a fixed descriptor
- //
- if (CurrentDescriptor->Index + 1 < sizeof(MemoryDescriptors) /
sizeof(MemoryDescriptors[0]))
- {
- //
- // Return next fixed descriptor
- //
- return &MemoryDescriptors[CurrentDescriptor->Index + 1].m;
- }
- else
- {
- //
- // No more fixed memory descriptor; end of memory map
- //
- return NULL;
- }
+ Current++;
+ if (Current->PageCount == 0) return NULL;
+ return Current;
}
}
@@ -269,6 +164,8 @@
#endif
TRACE("Initializing Memory Manager.\n");
+
+ BiosMemoryMap = MachVtbl.GetMemoryMap(&BiosMemoryMapEntryCount);
#if DBG
// Dump the system memory map
@@ -298,6 +195,26 @@
// Initialize the page lookup table
MmInitPageLookupTable(PageLookupTableAddress, TotalPagesInLookupTable);
+
+{
+ ULONG Type, Index, PrevIndex = 0;
+ PPAGE_LOOKUP_TABLE_ITEM RealPageLookupTable =
(PPAGE_LOOKUP_TABLE_ITEM)PageLookupTableAddress;
+
+ Type = RealPageLookupTable[0].PageAllocated;
+ for (Index = 1; Index < TotalPagesInLookupTable; Index++)
+ {
+ if ((RealPageLookupTable[Index].PageAllocated != Type) ||
+ (Index == TotalPagesInLookupTable - 1))
+ {
+ TRACE("Range: 0x%lx - 0x%lx Type=%d\n",
+ PrevIndex, Index - 1, Type);
+ Type = RealPageLookupTable[Index].PageAllocated;
+ PrevIndex = Index;
+ }
+ }
+}
+
+
MmUpdateLastFreePageHint(PageLookupTableAddress, TotalPagesInLookupTable);
FreePagesInLookupTable = MmCountFreePagesInLookupTable(PageLookupTableAddress,
TotalPagesInLookupTable);
@@ -305,6 +222,8 @@
MmInitializeHeap(PageLookupTableAddress);
TRACE("Memory Manager initialized. %d pages available.\n",
FreePagesInLookupTable);
+
+
return TRUE;
}
@@ -359,7 +278,7 @@
//
// Yes, remember it if this is real memory
//
- if (MemoryDescriptor->MemoryType == MemoryFree) MmLowestPhysicalPage =
MemoryDescriptor->BasePage;
+ MmLowestPhysicalPage = MemoryDescriptor->BasePage;
}
}
@@ -467,6 +386,10 @@
//
while ((MemoryDescriptor = ArcGetMemoryDescriptor(MemoryDescriptor)) != NULL)
{
+ TRACE("Got range: 0x%lx-0x%lx, type=%s\n",
+ MemoryDescriptor->BasePage,
+ MemoryDescriptor->BasePage + MemoryDescriptor->PageCount,
+ MmGetSystemMemoryMapTypeString(MemoryDescriptor->MemoryType));
//
// Convert ARC memory type to loader memory type
//
@@ -704,6 +627,9 @@
ULONG Index;
StartPage = MmGetPageNumberFromAddress(PageAddress);
+
+ if (StartPage < MmLowestPhysicalPage) return FALSE;
+
StartPage -= MmLowestPhysicalPage;
// Make sure they aren't trying to go past the