We now return memory map.
[reactos.git] / reactos / boot / freeldr / freeldr / mm / meminit.c
index f496073..bb87a9a 100644 (file)
@@ -1,6 +1,6 @@
 /*
  *  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>
-#include <arch.h>
-#include <mm.h>
-#include "mem.h"
-#include <rtl.h>
 #include <debug.h>
-#include <ui.h>
-#include <machine.h>
 
-
-#ifdef DEBUG
+#ifdef DBG
 typedef struct
 {
        ULONG           Type;
        UCHAR   TypeString[20];
-} MEMORY_TYPE, *PMEMORY_TYPE;
+} FREELDR_MEMORY_TYPE, *PFREELDR_MEMORY_TYPE;
 
 ULONG                          MemoryTypeCount = 5;
-MEMORY_TYPE            MemoryTypeArray[] =
+FREELDR_MEMORY_TYPE            MemoryTypeArray[] =
 {
        { 0, "Unknown Memory" },
-       { MEMTYPE_USABLE, "Usable Memory" },
-       { MEMTYPE_RESERVED, "Reserved Memory" },
-       { MEMTYPE_ACPI_RECLAIM, "ACPI Reclaim Memory" },
-       { MEMTYPE_ACPI_NVS, "ACPI NVS Memory" },
+       { BiosMemoryUsable, "Usable Memory" },
+       { BiosMemoryReserved, "Reserved Memory" },
+       { BiosMemoryAcpiReclaim, "ACPI Reclaim Memory" },
+       { BiosMemoryAcpiNvs, "ACPI NVS Memory" },
 };
 #endif
 
@@ -50,11 +43,14 @@ ULONG               TotalPagesInLookupTable = 0;
 ULONG          FreePagesInLookupTable = 0;
 ULONG          LastFreePageHint = 0;
 
-BOOL MmInitializeMemoryManager(VOID)
+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
 
@@ -64,7 +60,7 @@ BOOL MmInitializeMemoryManager(VOID)
 
        BiosMemoryMapEntryCount = MachGetMemoryMap(BiosMemoryMap, sizeof(BiosMemoryMap) / sizeof(BIOS_MEMORY_MAP));
 
-#ifdef DEBUG
+#ifdef DBG
        // Dump the system memory map
        if (BiosMemoryMapEntryCount != 0)
        {
@@ -82,6 +78,7 @@ BOOL MmInitializeMemoryManager(VOID)
                MmFixupSystemMemoryMap(BiosMemoryMap, &BiosMemoryMapEntryCount);
        }
 
+       // Find address for the page lookup table
        TotalPagesInLookupTable = MmGetAddressablePageCountIncludingHoles(BiosMemoryMap, BiosMemoryMapEntryCount);
        PageLookupTableAddress = MmFindLocationForPageLookupTable(BiosMemoryMap, BiosMemoryMapEntryCount);
        LastFreePageHint = TotalPagesInLookupTable;
@@ -95,16 +92,65 @@ BOOL MmInitializeMemoryManager(VOID)
                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;
@@ -193,13 +239,21 @@ PVOID MmFindLocationForPageLookupTable(PBIOS_MEMORY_MAP BiosMemoryMap, ULONG Map
        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 == MEMTYPE_USABLE && 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;
                }
        }
@@ -246,54 +300,66 @@ VOID MmInitPageLookupTable(PVOID PageLookupTable, ULONG TotalPageCount, PBIOS_ME
        // 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 == MEMTYPE_USABLE) ? 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, MEMTYPE_RESERVED);
-
-       // 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, MEMTYPE_RESERVED);
+       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;
        }
 }
@@ -307,7 +373,7 @@ ULONG MmCountFreePagesInLookupTable(PVOID PageLookupTable, ULONG TotalPageCount)
        FreePageCount = 0;
        for (Index=0; Index<TotalPageCount; Index++)
        {
-               if (RealPageLookupTable[Index].PageAllocated == 0)
+               if (RealPageLookupTable[Index].PageAllocated == LoaderFree)
                {
                        FreePageCount++;
                }
@@ -316,7 +382,7 @@ ULONG MmCountFreePagesInLookupTable(PVOID PageLookupTable, ULONG TotalPageCount)
        return FreePageCount;
 }
 
-ULONG MmFindAvailablePagesFromEnd(PVOID PageLookupTable, ULONG TotalPageCount, ULONG PagesNeeded)
+ULONG MmFindAvailablePages(PVOID PageLookupTable, ULONG TotalPageCount, ULONG PagesNeeded, BOOLEAN FromEnd)
 {
        PPAGE_LOOKUP_TABLE_ITEM         RealPageLookupTable = (PPAGE_LOOKUP_TABLE_ITEM)PageLookupTable;
        ULONG                                                   AvailablePagesSoFar;
@@ -328,21 +394,47 @@ ULONG MmFindAvailablePagesFromEnd(PVOID PageLookupTable, ULONG TotalPageCount, U
        }
 
        AvailablePagesSoFar = 0;
-       for (Index=LastFreePageHint-1; Index>0; Index--)
+       if (FromEnd)
        {
-               if (RealPageLookupTable[Index].PageAllocated != 0)
+               /* Allocate "high" (from end) pages */
+               for (Index=LastFreePageHint-1; Index>0; Index--)
                {
-                       AvailablePagesSoFar = 0;
-                       continue;
+                       if (RealPageLookupTable[Index].PageAllocated != LoaderFree)
+                       {
+                               AvailablePagesSoFar = 0;
+                               continue;
+                       }
+                       else
+                       {
+                               AvailablePagesSoFar++;
+                       }
+
+                       if (AvailablePagesSoFar >= PagesNeeded)
+                       {
+                               return Index;
+                       }
                }
-               else
+       }
+       else
+       {
+               DbgPrint((DPRINT_MEMORY, "Alloc low memory, LastFreePageHint %d, TPC %d\n", LastFreePageHint, TotalPageCount));
+               /* Allocate "low" pages */
+               for (Index=1; Index < LastFreePageHint; Index++)
                {
-                       AvailablePagesSoFar++;
-               }
+                       if (RealPageLookupTable[Index].PageAllocated != LoaderFree)
+                       {
+                               AvailablePagesSoFar = 0;
+                               continue;
+                       }
+                       else
+                       {
+                               AvailablePagesSoFar++;
+                       }
 
-               if (AvailablePagesSoFar >= PagesNeeded)
-               {
-                       return Index;
+                       if (AvailablePagesSoFar >= PagesNeeded)
+                       {
+                               return Index - AvailablePagesSoFar + 1;
+                       }
                }
        }
 
@@ -357,13 +449,13 @@ ULONG MmFindAvailablePagesBeforePage(PVOID PageLookupTable, ULONG TotalPageCount
 
        if (LastPage > TotalPageCount)
        {
-               return MmFindAvailablePagesFromEnd(PageLookupTable, TotalPageCount, PagesNeeded);
+               return MmFindAvailablePages(PageLookupTable, TotalPageCount, PagesNeeded, TRUE);
        }
 
        AvailablePagesSoFar = 0;
        for (Index=LastPage-1; Index>0; Index--)
        {
-               if (RealPageLookupTable[Index].PageAllocated != 0)
+               if (RealPageLookupTable[Index].PageAllocated != LoaderFree)
                {
                        AvailablePagesSoFar = 0;
                        continue;
@@ -384,8 +476,8 @@ ULONG MmFindAvailablePagesBeforePage(PVOID PageLookupTable, ULONG TotalPageCount
 
 VOID MmFixupSystemMemoryMap(PBIOS_MEMORY_MAP BiosMemoryMap, ULONG* MapCount)
 {
-       int             Index;
-       int             Index2;
+       UINT            Index;
+       UINT            Index2;
 
        // Loop through each entry in the array
        for (Index=0; Index<*MapCount; Index++)
@@ -393,7 +485,7 @@ VOID MmFixupSystemMemoryMap(PBIOS_MEMORY_MAP BiosMemoryMap, ULONG* MapCount)
                // 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 (BiosMemoryMap[Index].Type != MEMTYPE_USABLE)
+               if (BiosMemoryMap[Index].Type != BiosMemoryUsable)
                {
                        // Slide every entry after this down one
                        for (Index2=Index; Index2<(*MapCount - 1); Index2++)
@@ -413,7 +505,7 @@ VOID MmUpdateLastFreePageHint(PVOID PageLookupTable, ULONG TotalPageCount)
 
        for (Index=TotalPageCount-1; Index>0; Index--)
        {
-               if (RealPageLookupTable[Index].PageAllocated == 0)
+               if (RealPageLookupTable[Index].PageAllocated == LoaderFree)
                {
                        LastFreePageHint = Index + 1;
                        break;
@@ -421,7 +513,7 @@ VOID MmUpdateLastFreePageHint(PVOID PageLookupTable, ULONG TotalPageCount)
        }
 }
 
-BOOL MmAreMemoryPagesAvailable(PVOID PageLookupTable, ULONG TotalPageCount, PVOID PageAddress, ULONG PageCount)
+BOOLEAN MmAreMemoryPagesAvailable(PVOID PageLookupTable, ULONG TotalPageCount, PVOID PageAddress, ULONG PageCount)
 {
        PPAGE_LOOKUP_TABLE_ITEM         RealPageLookupTable = (PPAGE_LOOKUP_TABLE_ITEM)PageLookupTable;
        ULONG                                                   StartPage;
@@ -440,7 +532,7 @@ BOOL MmAreMemoryPagesAvailable(PVOID PageLookupTable, ULONG TotalPageCount, PVOI
        {
                // 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;
                }