[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.

svn path=/trunk/; revision=53816
This commit is contained in:
Timo Kreuzer 2011-09-23 17:35:45 +00:00
parent 184aeeeeef
commit 5f22a73516
9 changed files with 252 additions and 238 deletions

View file

@ -143,12 +143,25 @@ ArmHwDetect(VOID)
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

View file

@ -21,6 +21,7 @@
*/
#include <freeldr.h>
#include <arch/pc/x86common.h>
#define NDEBUG
#include <debug.h>
@ -28,10 +29,44 @@
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
GetExtendedMemoryConfiguration(ULONG* pMemoryAtOneMB /* in KB */, ULONG* pMemoryAtSixteenMB /* in 64KB */)
@ -153,11 +188,14 @@ PcMemGetConventionalMemorySize(VOID)
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 @@ PcMemGetBiosMemoryMap(PBIOS_MEMORY_MAP BiosMemoryMap, ULONG MaxMemoryMapSize)
*/
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 @@ PcMemGetBiosMemoryMap(PBIOS_MEMORY_MAP BiosMemoryMap, ULONG MaxMemoryMapSize)
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,15 +244,40 @@ PcMemGetBiosMemoryMap(PBIOS_MEMORY_MAP BiosMemoryMap, ULONG MaxMemoryMapSize)
break;
}
/* Copy data to caller's buffer */
RtlCopyMemory(&BiosMemoryMap[MapCount], (PVOID)BIOSCALLBUFFER, Regs.x.ecx);
/* Copy data to global buffer */
RtlCopyMemory(&PcBiosMemoryMap[PcBiosMapCount], (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);
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
* the last entry so we're done */
@ -229,46 +292,59 @@ PcMemGetBiosMemoryMap(PBIOS_MEMORY_MAP BiosMemoryMap, ULONG MaxMemoryMapSize)
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++;
/* Conventional memory */
AddMemoryDescriptor(PcMemoryMap,
MAX_BIOS_DESCRIPTORS,
0,
PcMemGetConventionalMemorySize() * 1024 / PAGE_SIZE,
MemoryFree);
/* Extended memory at 1MB */
PcBiosMemoryMap[EntryCount].BaseAddress = 1024 * 1024;
PcBiosMemoryMap[EntryCount].Length = ExtendedMemorySizeAtOneMB * 1024;
PcBiosMemoryMap[EntryCount].Type = BiosMemoryUsable;
/* 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 */

View file

@ -75,21 +75,21 @@ XboxMemInit(VOID)
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;

View file

@ -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 @@ ULONG DebugPrintMask = DPRINT_INIFILE;
#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

View file

@ -49,7 +49,7 @@ VOID XboxPrepareForReactOS(IN BOOLEAN Setup);
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);

View file

@ -46,7 +46,7 @@ VOID PcVideoSync(VOID);
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);

View file

@ -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 */

View file

@ -1,5 +1,4 @@
/* $Id$
*
/*
* FreeLoader
*
* This program is free software; you can redistribute it and/or modify
@ -59,7 +58,7 @@ typedef struct tagMACHVTBL
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);

View file

@ -53,211 +53,106 @@ ULONG LastFreePageHint = 0;
ULONG MmLowestPhysicalPage = 0xFFFFFFFF;
ULONG MmHighestPhysicalPage = 0;
PMEMORY_DESCRIPTOR BiosMemoryMap;
ULONG BiosMemoryMapEntryCount;
extern ULONG_PTR MmHeapPointer;
extern ULONG_PTR MmHeapStart;
typedef struct
ULONG
AddMemoryDescriptor(
IN OUT PMEMORY_DESCRIPTOR List,
IN ULONG MaxCount,
IN PFN_NUMBER BasePage,
IN PFN_NUMBER PageCount,
IN MEMORY_TYPE MemoryType)
{
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
ULONG i, c;
PFN_NUMBER NextBase;
TRACE("AddMemoryDescriptor(0x%lx-0x%lx [0x%lx pages])\n",
BasePage, BasePage + PageCount, PageCount);
#endif
};
/* 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++;
}
static
VOID MmFixupSystemMemoryMap(PBIOS_MEMORY_MAP BiosMemoryMap, ULONG* MapCount)
{
int Index;
int Index2;
ULONGLONG BaseAddressOffset;
/* Check if the list is full */
if (c >= MaxCount) return c;
// 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);
/* 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;
// 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--;
}
}
/* 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;
}
}
@ -270,6 +165,8 @@ BOOLEAN MmInitializeMemoryManager(VOID)
TRACE("Initializing Memory Manager.\n");
BiosMemoryMap = MachVtbl.GetMemoryMap(&BiosMemoryMapEntryCount);
#if DBG
// Dump the system memory map
TRACE("System Memory Map (Base Address, Length, Type):\n");
@ -298,6 +195,26 @@ BOOLEAN MmInitializeMemoryManager(VOID)
// 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 @@ BOOLEAN MmInitializeMemoryManager(VOID)
MmInitializeHeap(PageLookupTableAddress);
TRACE("Memory Manager initialized. %d pages available.\n", FreePagesInLookupTable);
return TRUE;
}
@ -359,7 +278,7 @@ ULONG MmGetAddressablePageCountIncludingHoles(VOID)
//
// Yes, remember it if this is real memory
//
if (MemoryDescriptor->MemoryType == MemoryFree) MmLowestPhysicalPage = MemoryDescriptor->BasePage;
MmLowestPhysicalPage = MemoryDescriptor->BasePage;
}
}
@ -467,6 +386,10 @@ VOID MmInitPageLookupTable(PVOID PageLookupTable, ULONG TotalPageCount)
//
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 @@ BOOLEAN MmAreMemoryPagesAvailable(PVOID PageLookupTable, ULONG TotalPageCount, P
ULONG Index;
StartPage = MmGetPageNumberFromAddress(PageAddress);
if (StartPage < MmLowestPhysicalPage) return FALSE;
StartPage -= MmLowestPhysicalPage;
// Make sure they aren't trying to go past the