/*
* FreeLoader
- * Copyright (C) 1998-2003 Brian Palmer <brianp@sginet.com>
+ * Copyright (C) 2006-2008 Aleksey Bragin <aleksey@reactos.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
*/
#include <freeldr.h>
-
-#define NDEBUG
#include <debug.h>
-#ifdef DEBUG
+#ifdef DBG
typedef struct
{
ULONG Type;
ULONG FreePagesInLookupTable = 0;
ULONG LastFreePageHint = 0;
+extern ULONG_PTR MmHeapPointer;
+extern ULONG_PTR MmHeapStart;
+
BOOLEAN MmInitializeMemoryManager(VOID)
{
BIOS_MEMORY_MAP BiosMemoryMap[32];
ULONG BiosMemoryMapEntryCount;
-#ifdef DEBUG
+#ifdef DBG
ULONG Index;
#endif
BiosMemoryMapEntryCount = MachGetMemoryMap(BiosMemoryMap, sizeof(BiosMemoryMap) / sizeof(BIOS_MEMORY_MAP));
-#ifdef DEBUG
+#ifdef DBG
// Dump the system memory map
if (BiosMemoryMapEntryCount != 0)
{
MmFixupSystemMemoryMap(BiosMemoryMap, &BiosMemoryMapEntryCount);
}
+ // Find address for the page lookup table
TotalPagesInLookupTable = MmGetAddressablePageCountIncludingHoles(BiosMemoryMap, BiosMemoryMapEntryCount);
PageLookupTableAddress = MmFindLocationForPageLookupTable(BiosMemoryMap, BiosMemoryMapEntryCount);
LastFreePageHint = TotalPagesInLookupTable;
return FALSE;
}
+ // Initialize the page lookup table
MmInitPageLookupTable(PageLookupTableAddress, TotalPagesInLookupTable, BiosMemoryMap, BiosMemoryMapEntryCount);
MmUpdateLastFreePageHint(PageLookupTableAddress, TotalPagesInLookupTable);
+ // Add machine-dependent stuff
+#ifdef __i386__
+ MmMarkPagesInLookupTable(PageLookupTableAddress, 0x00, 1, LoaderFirmwarePermanent); // realmode int vectors
+ MmMarkPagesInLookupTable(PageLookupTableAddress, 0x01, 7, LoaderFirmwareTemporary); // freeldr stack + cmdline
+ MmMarkPagesInLookupTable(PageLookupTableAddress, 0x08, 0x70, LoaderLoadedProgram); // freeldr image (roughly max. 0x64 pages)
+ MmMarkPagesInLookupTable(PageLookupTableAddress, 0x78, 8, LoaderOsloaderStack); // prot mode stack. BIOSCALLBUFFER
+ MmMarkPagesInLookupTable(PageLookupTableAddress, 0x80, 0x10, LoaderOsloaderHeap); // File system read buffer. FILESYSBUFFER
+ MmMarkPagesInLookupTable(PageLookupTableAddress, 0x90, 0x10, LoaderOsloaderHeap); // Disk read buffer for int 13h. DISKREADBUFFER
+ MmMarkPagesInLookupTable(PageLookupTableAddress, 0xA0, 0x60, LoaderFirmwarePermanent); // ROM / Video
+ MmMarkPagesInLookupTable(PageLookupTableAddress, 0xFFF, 1, LoaderSpecialMemory); // unusable memory
+#elif __arm__
+ MmMarkPagesInLookupTable(PageLookupTableAddress, 0x00, 1, LoaderFirmwarePermanent); // arm exception handlers
+ MmMarkPagesInLookupTable(PageLookupTableAddress, 0x01, 7, LoaderFirmwareTemporary); // arm board block + freeldr stack + cmdline
+ MmMarkPagesInLookupTable(PageLookupTableAddress, 0x08, 0x70, LoaderLoadedProgram); // freeldr image (roughly max. 0x64 pages)
+#endif
+
FreePagesInLookupTable = MmCountFreePagesInLookupTable(PageLookupTableAddress, TotalPagesInLookupTable);
+ MmInitializeHeap(PageLookupTableAddress);
+
DbgPrint((DPRINT_MEMORY, "Memory Manager initialized. %d pages available.\n", FreePagesInLookupTable));
return TRUE;
}
-#ifdef DEBUG
+VOID MmInitializeHeap(PVOID PageLookupTable)
+{
+ ULONG PagesNeeded;
+ ULONG HeapStart;
+
+ // HACK: Make it so it doesn't overlap kernel space
+ MmMarkPagesInLookupTable(PageLookupTableAddress, 0x100, 0xFF, LoaderSystemCode);
+
+ // Find contigious memory block for HEAP:STACK
+ PagesNeeded = HEAP_PAGES + STACK_PAGES;
+ HeapStart = MmFindAvailablePages(PageLookupTable, TotalPagesInLookupTable, PagesNeeded, FALSE);
+
+ // Unapply the hack
+ MmMarkPagesInLookupTable(PageLookupTableAddress, 0x100, 0xFF, LoaderFree);
+
+ if (HeapStart == 0)
+ {
+ UiMessageBox("Critical error: Can't allocate heap!");
+ return;
+ }
+
+ // Initialize BGET
+ bpool(HeapStart << MM_PAGE_SHIFT, PagesNeeded << MM_PAGE_SHIFT);
+
+ // Mark those pages as used
+ MmMarkPagesInLookupTable(PageLookupTableAddress, HeapStart, PagesNeeded, LoaderOsloaderHeap);
+
+ DbgPrint((DPRINT_MEMORY, "Heap initialized, base 0x%08x, pages %d\n", (HeapStart << MM_PAGE_SHIFT), PagesNeeded));
+}
+
+#ifdef DBG
PUCHAR MmGetSystemMemoryMapTypeString(ULONG Type)
{
ULONG Index;
RtlCopyMemory(TempBiosMemoryMap, BiosMemoryMap, sizeof(BIOS_MEMORY_MAP) * 32);
MmSortBiosMemoryMap(TempBiosMemoryMap, MapCount);
+ // Find a place, starting from the highest memory
+ // (thus leaving low memory for kernel/drivers)
for (Index=(MapCount-1); Index>=0; Index--)
{
// If this is usable memory with a big enough length
// then we'll put our page lookup table here
- if (TempBiosMemoryMap[Index].Type == BiosMemoryUsable && TempBiosMemoryMap[Index].Length >= PageLookupTableSize)
+
+ // skip if this is not usable region
+ if (TempBiosMemoryMap[Index].Type != BiosMemoryUsable)
+ continue;
+
+ if (TempBiosMemoryMap[Index].Length >= PageLookupTableSize)
{
- PageLookupTableMemAddress = (PVOID)(ULONG)(TempBiosMemoryMap[Index].BaseAddress + (TempBiosMemoryMap[Index].Length - PageLookupTableSize));
+ PageLookupTableMemAddress = (PVOID)(ULONG)
+ (TempBiosMemoryMap[Index].BaseAddress + (TempBiosMemoryMap[Index].Length - PageLookupTableSize));
break;
}
}
// Mark every page as allocated initially
// We will go through and mark pages again according to the memory map
// But this will mark any holes not described in the map as allocated
- MmMarkPagesInLookupTable(PageLookupTable, 0, TotalPageCount, 1);
+ MmMarkPagesInLookupTable(PageLookupTable, 0, TotalPageCount, LoaderFirmwarePermanent);
for (Index=0; Index<MapCount; Index++)
{
MemoryMapStartPage = MmGetPageNumberFromAddress((PVOID)(ULONG)BiosMemoryMap[Index].BaseAddress);
MemoryMapEndPage = MmGetPageNumberFromAddress((PVOID)(ULONG)(BiosMemoryMap[Index].BaseAddress + BiosMemoryMap[Index].Length - 1));
MemoryMapPageCount = (MemoryMapEndPage - MemoryMapStartPage) + 1;
- MemoryMapPageAllocated = (BiosMemoryMap[Index].Type == BiosMemoryUsable) ? 0 : BiosMemoryMap[Index].Type;
+
+ switch (BiosMemoryMap[Index].Type)
+ {
+ case BiosMemoryUsable:
+ MemoryMapPageAllocated = LoaderFree;
+ break;
+
+ case BiosMemoryAcpiReclaim:
+ case BiosMemoryAcpiNvs:
+ MemoryMapPageAllocated = LoaderSpecialMemory;
+ break;
+
+ default:
+ MemoryMapPageAllocated = LoaderSpecialMemory;
+ }
DbgPrint((DPRINT_MEMORY, "Marking pages as type %d: StartPage: %d PageCount: %d\n", MemoryMapPageAllocated, MemoryMapStartPage, MemoryMapPageCount));
MmMarkPagesInLookupTable(PageLookupTable, MemoryMapStartPage, MemoryMapPageCount, MemoryMapPageAllocated);
}
- // Mark the low memory region below 1MB as reserved (256 pages in region)
- DbgPrint((DPRINT_MEMORY, "Marking the low 1MB region as reserved.\n"));
- MmMarkPagesInLookupTable(PageLookupTable, 0, 256, BiosMemoryReserved);
-
- // Mark the pages that the lookup tabel occupies as reserved
+ // Mark the pages that the lookup table occupies as reserved
PageLookupTableStartPage = MmGetPageNumberFromAddress(PageLookupTable);
PageLookupTablePageCount = MmGetPageNumberFromAddress((PVOID)((ULONG_PTR)PageLookupTable + ROUND_UP(TotalPageCount * sizeof(PAGE_LOOKUP_TABLE_ITEM), MM_PAGE_SIZE))) - PageLookupTableStartPage;
DbgPrint((DPRINT_MEMORY, "Marking the page lookup table pages as reserved StartPage: %d PageCount: %d\n", PageLookupTableStartPage, PageLookupTablePageCount));
- MmMarkPagesInLookupTable(PageLookupTable, PageLookupTableStartPage, PageLookupTablePageCount, BiosMemoryReserved);
+ MmMarkPagesInLookupTable(PageLookupTable, PageLookupTableStartPage, PageLookupTablePageCount, LoaderFirmwareTemporary);
}
-VOID MmMarkPagesInLookupTable(PVOID PageLookupTable, ULONG StartPage, ULONG PageCount, ULONG PageAllocated)
+VOID MmMarkPagesInLookupTable(PVOID PageLookupTable, ULONG StartPage, ULONG PageCount, TYPE_OF_MEMORY PageAllocated)
{
PPAGE_LOOKUP_TABLE_ITEM RealPageLookupTable = (PPAGE_LOOKUP_TABLE_ITEM)PageLookupTable;
ULONG Index;
for (Index=StartPage; Index<(StartPage+PageCount); Index++)
{
+#if 0
if ((Index <= (StartPage + 16)) || (Index >= (StartPage+PageCount-16)))
{
DbgPrint((DPRINT_MEMORY, "Index = %d StartPage = %d PageCount = %d\n", Index, StartPage, PageCount));
}
+#endif
RealPageLookupTable[Index].PageAllocated = PageAllocated;
- RealPageLookupTable[Index].PageAllocationLength = PageAllocated ? 1 : 0;
+ RealPageLookupTable[Index].PageAllocationLength = (PageAllocated != LoaderFree) ? 1 : 0;
}
DbgPrint((DPRINT_MEMORY, "MmMarkPagesInLookupTable() Done\n"));
}
-VOID MmAllocatePagesInLookupTable(PVOID PageLookupTable, ULONG StartPage, ULONG PageCount)
+VOID MmAllocatePagesInLookupTable(PVOID PageLookupTable, ULONG StartPage, ULONG PageCount, TYPE_OF_MEMORY MemoryType)
{
PPAGE_LOOKUP_TABLE_ITEM RealPageLookupTable = (PPAGE_LOOKUP_TABLE_ITEM)PageLookupTable;
ULONG Index;
for (Index=StartPage; Index<(StartPage+PageCount); Index++)
{
- RealPageLookupTable[Index].PageAllocated = 1;
+ RealPageLookupTable[Index].PageAllocated = MemoryType;
RealPageLookupTable[Index].PageAllocationLength = (Index == StartPage) ? PageCount : 0;
}
}
FreePageCount = 0;
for (Index=0; Index<TotalPageCount; Index++)
{
- if (RealPageLookupTable[Index].PageAllocated == 0)
+ if (RealPageLookupTable[Index].PageAllocated == LoaderFree)
{
FreePageCount++;
}
/* Allocate "high" (from end) pages */
for (Index=LastFreePageHint-1; Index>0; Index--)
{
- if (RealPageLookupTable[Index].PageAllocated != 0)
+ if (RealPageLookupTable[Index].PageAllocated != LoaderFree)
{
AvailablePagesSoFar = 0;
continue;
/* Allocate "low" pages */
for (Index=1; Index < LastFreePageHint; Index++)
{
- if (RealPageLookupTable[Index].PageAllocated != 0)
+ if (RealPageLookupTable[Index].PageAllocated != LoaderFree)
{
AvailablePagesSoFar = 0;
continue;
if (AvailablePagesSoFar >= PagesNeeded)
{
- return Index;
+ return Index - AvailablePagesSoFar + 1;
}
}
}
AvailablePagesSoFar = 0;
for (Index=LastPage-1; Index>0; Index--)
{
- if (RealPageLookupTable[Index].PageAllocated != 0)
+ if (RealPageLookupTable[Index].PageAllocated != LoaderFree)
{
AvailablePagesSoFar = 0;
continue;
for (Index=TotalPageCount-1; Index>0; Index--)
{
- if (RealPageLookupTable[Index].PageAllocated == 0)
+ if (RealPageLookupTable[Index].PageAllocated == LoaderFree)
{
LastFreePageHint = Index + 1;
break;
{
// If this page is allocated then there obviously isn't
// memory availabe so return FALSE
- if (RealPageLookupTable[Index].PageAllocated != 0)
+ if (RealPageLookupTable[Index].PageAllocated != LoaderFree)
{
return FALSE;
}