X-Git-Url: https://git.reactos.org/?p=reactos.git;a=blobdiff_plain;f=boot%2Ffreeldr%2Ffreeldr%2Fmm%2Fmeminit.c;h=f59a43f7b54d202f4efabbe6b5f24a8a8c560797;hp=079bf4dbde85f38aa193c85e845502c65ee637fd;hb=e4a060ead45b9dc87a64408b6d791ea4a5fef55e;hpb=79e9ba171b07100f209c1abca802d015cef7b522 diff --git a/boot/freeldr/freeldr/mm/meminit.c b/boot/freeldr/freeldr/mm/meminit.c index 079bf4dbde8..f59a43f7b54 100644 --- a/boot/freeldr/freeldr/mm/meminit.c +++ b/boot/freeldr/freeldr/mm/meminit.c @@ -1,6 +1,7 @@ /* * FreeLoader * Copyright (C) 2006-2008 Aleksey Bragin + * Copyright (C) 2006-2009 Hervé Poussineau * * 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 @@ -12,30 +13,35 @@ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include #include -#ifdef DBG +#if DBG typedef struct { - ULONG Type; - UCHAR TypeString[20]; + MEMORY_TYPE Type; + PCSTR TypeString; } FREELDR_MEMORY_TYPE, *PFREELDR_MEMORY_TYPE; -ULONG MemoryTypeCount = 5; -FREELDR_MEMORY_TYPE MemoryTypeArray[] = +FREELDR_MEMORY_TYPE MemoryTypeArray[] = { - { 0, "Unknown Memory" }, - { BiosMemoryUsable, "Usable Memory" }, - { BiosMemoryReserved, "Reserved Memory" }, - { BiosMemoryAcpiReclaim, "ACPI Reclaim Memory" }, - { BiosMemoryAcpiNvs, "ACPI NVS Memory" }, + { MemoryMaximum, "Unknown memory" }, + { MemoryExceptionBlock, "Exception block" }, + { MemorySystemBlock, "System block" }, + { MemoryFree, "Free memory" }, + { MemoryBad, "Bad memory" }, + { MemoryLoadedProgram, "Loaded program" }, + { MemoryFirmwareTemporary, "Firmware temporary" }, + { MemoryFirmwarePermanent, "Firmware permanent" }, + { MemoryFreeContiguous, "Free contiguous memory" }, + { MemorySpecialMemory, "Special memory" }, }; +ULONG MemoryTypeCount = sizeof(MemoryTypeArray) / sizeof(MemoryTypeArray[0]); #endif PVOID PageLookupTableAddress = NULL; @@ -48,39 +54,27 @@ extern ULONG_PTR MmHeapStart; BOOLEAN MmInitializeMemoryManager(VOID) { - BIOS_MEMORY_MAP BiosMemoryMap[32]; - ULONG BiosMemoryMapEntryCount; -#ifdef DBG - ULONG Index; +#if DBG + MEMORY_DESCRIPTOR* MemoryDescriptor = NULL; #endif - DbgPrint((DPRINT_MEMORY, "Initializing Memory Manager.\n")); - - RtlZeroMemory(BiosMemoryMap, sizeof(BIOS_MEMORY_MAP) * 32); - - BiosMemoryMapEntryCount = MachGetMemoryMap(BiosMemoryMap, sizeof(BiosMemoryMap) / sizeof(BIOS_MEMORY_MAP)); + DPRINTM(DPRINT_MEMORY, "Initializing Memory Manager.\n"); -#ifdef DBG +#if DBG // Dump the system memory map - if (BiosMemoryMapEntryCount != 0) + DPRINTM(DPRINT_MEMORY, "System Memory Map (Base Address, Length, Type):\n"); + while ((MemoryDescriptor = ArcGetMemoryDescriptor(MemoryDescriptor)) != NULL) { - DbgPrint((DPRINT_MEMORY, "System Memory Map (Base Address, Length, Type):\n")); - for (Index=0; IndexBasePage * MM_PAGE_SIZE, + MemoryDescriptor->PageCount * MM_PAGE_SIZE, + MmGetSystemMemoryMapTypeString(MemoryDescriptor->MemoryType)); } #endif - // If we got the system memory map then fixup invalid entries - if (BiosMemoryMapEntryCount != 0) - { - MmFixupSystemMemoryMap(BiosMemoryMap, &BiosMemoryMapEntryCount); - } - // Find address for the page lookup table - TotalPagesInLookupTable = MmGetAddressablePageCountIncludingHoles(BiosMemoryMap, BiosMemoryMapEntryCount); - PageLookupTableAddress = MmFindLocationForPageLookupTable(BiosMemoryMap, BiosMemoryMapEntryCount); + TotalPagesInLookupTable = MmGetAddressablePageCountIncludingHoles(); + PageLookupTableAddress = MmFindLocationForPageLookupTable(TotalPagesInLookupTable); LastFreePageHint = TotalPagesInLookupTable; if (PageLookupTableAddress == 0) @@ -93,30 +87,14 @@ BOOLEAN MmInitializeMemoryManager(VOID) } // Initialize the page lookup table - MmInitPageLookupTable(PageLookupTableAddress, TotalPagesInLookupTable, BiosMemoryMap, BiosMemoryMapEntryCount); + MmInitPageLookupTable(PageLookupTableAddress, TotalPagesInLookupTable); 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)); + DPRINTM(DPRINT_MEMORY, "Memory Manager initialized. %d pages available.\n", FreePagesInLookupTable); return TRUE; } @@ -124,8 +102,11 @@ VOID MmInitializeHeap(PVOID PageLookupTable) { ULONG PagesNeeded; ULONG HeapStart; - + MEMORY_TYPE Type; + PPAGE_LOOKUP_TABLE_ITEM RealPageLookupTable = (PPAGE_LOOKUP_TABLE_ITEM)PageLookupTable; + // HACK: Make it so it doesn't overlap kernel space + Type = RealPageLookupTable[0x100].PageAllocated; MmMarkPagesInLookupTable(PageLookupTableAddress, 0x100, 0xFF, LoaderSystemCode); // Find contigious memory block for HEAP:STACK @@ -133,7 +114,7 @@ VOID MmInitializeHeap(PVOID PageLookupTable) HeapStart = MmFindAvailablePages(PageLookupTable, TotalPagesInLookupTable, PagesNeeded, FALSE); // Unapply the hack - MmMarkPagesInLookupTable(PageLookupTableAddress, 0x100, 0xFF, LoaderFree); + MmMarkPagesInLookupTable(PageLookupTableAddress, 0x100, 0xFF, Type); if (HeapStart == 0) { @@ -147,11 +128,11 @@ VOID MmInitializeHeap(PVOID PageLookupTable) // 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)); + DPRINTM(DPRINT_MEMORY, "Heap initialized, base 0x%08x, pages %d\n", (HeapStart << MM_PAGE_SHIFT), PagesNeeded); } -#ifdef DBG -PUCHAR MmGetSystemMemoryMapTypeString(ULONG Type) +#if DBG +PCSTR MmGetSystemMemoryMapTypeString(MEMORY_TYPE Type) { ULONG Index; @@ -172,165 +153,189 @@ ULONG MmGetPageNumberFromAddress(PVOID Address) return ((ULONG_PTR)Address) / MM_PAGE_SIZE; } -PVOID MmGetEndAddressOfAnyMemory(PBIOS_MEMORY_MAP BiosMemoryMap, ULONG MapCount) +ULONG MmGetAddressablePageCountIncludingHoles(VOID) { - ULONGLONG MaxStartAddressSoFar; - ULONGLONG EndAddressOfMemory; - ULONG Index; - - MaxStartAddressSoFar = 0; - EndAddressOfMemory = 0; - for (Index=0; Index 0xFFFFFFFF) - { - EndAddressOfMemory = 0xFFFFFFFF; - } - } - } - - DbgPrint((DPRINT_MEMORY, "MmGetEndAddressOfAnyMemory() returning 0x%x\n", (ULONG)EndAddressOfMemory)); - - return (PVOID)(ULONG_PTR)EndAddressOfMemory; -} - -ULONG MmGetAddressablePageCountIncludingHoles(PBIOS_MEMORY_MAP BiosMemoryMap, ULONG MapCount) -{ - ULONG PageCount; - ULONGLONG EndAddress; - - EndAddress = (ULONGLONG)(ULONG_PTR)MmGetEndAddressOfAnyMemory(BiosMemoryMap, MapCount); - - // Since MmGetEndAddressOfAnyMemory() won't - // return addresses higher than 0xFFFFFFFF - // then we need to adjust the end address - // to 0x100000000 so we don't get an - // off-by-one error - if (EndAddress >= 0xFFFFFFFF) - { - EndAddress = 0x100000000LL; - - DbgPrint((DPRINT_MEMORY, "MmGetEndAddressOfAnyMemory() returned 0xFFFFFFFF, correcting to be 0x100000000.\n")); - } - - PageCount = (EndAddress / MM_PAGE_SIZE); - - DbgPrint((DPRINT_MEMORY, "MmGetAddressablePageCountIncludingHoles() returning %d\n", PageCount)); - - return PageCount; -} - -PVOID MmFindLocationForPageLookupTable(PBIOS_MEMORY_MAP BiosMemoryMap, ULONG MapCount) -{ - ULONG TotalPageCount; - ULONG PageLookupTableSize; - PVOID PageLookupTableMemAddress; - int Index; - BIOS_MEMORY_MAP TempBiosMemoryMap[32]; - - TotalPageCount = MmGetAddressablePageCountIncludingHoles(BiosMemoryMap, MapCount); - PageLookupTableSize = TotalPageCount * sizeof(PAGE_LOOKUP_TABLE_ITEM); - PageLookupTableMemAddress = 0; - - 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 - - // skip if this is not usable region - if (TempBiosMemoryMap[Index].Type != BiosMemoryUsable) - continue; - - if (TempBiosMemoryMap[Index].Length >= PageLookupTableSize) - { - PageLookupTableMemAddress = (PVOID)(ULONG_PTR) - (TempBiosMemoryMap[Index].BaseAddress + (TempBiosMemoryMap[Index].Length - PageLookupTableSize)); - break; - } - } - - DbgPrint((DPRINT_MEMORY, "MmFindLocationForPageLookupTable() returning 0x%x\n", PageLookupTableMemAddress)); - - return PageLookupTableMemAddress; + MEMORY_DESCRIPTOR* MemoryDescriptor = NULL; + ULONG EndPage = 0; + + // + // Go through the whole memory map to get max address + // + while ((MemoryDescriptor = ArcGetMemoryDescriptor(MemoryDescriptor)) != NULL) + { + // + // Check if we got a higher end page address + // + if (MemoryDescriptor->BasePage + MemoryDescriptor->PageCount > EndPage) + { + // + // Yes, remember it + // + EndPage = MemoryDescriptor->BasePage + MemoryDescriptor->PageCount; + } + } + + DPRINTM(DPRINT_MEMORY, "MmGetAddressablePageCountIncludingHoles() returning 0x%x\n", EndPage); + + return EndPage; } -VOID MmSortBiosMemoryMap(PBIOS_MEMORY_MAP BiosMemoryMap, ULONG MapCount) +PVOID MmFindLocationForPageLookupTable(ULONG TotalPageCount) { - ULONG Index; - ULONG LoopCount; - BIOS_MEMORY_MAP TempMapItem; - - // Loop once for each entry in the memory map minus one - // On each loop iteration go through and sort the memory map - for (LoopCount=0; LoopCount<(MapCount-1); LoopCount++) - { - for (Index=0; Index<(MapCount-1); Index++) - { - if (BiosMemoryMap[Index].BaseAddress > BiosMemoryMap[Index+1].BaseAddress) - { - TempMapItem = BiosMemoryMap[Index]; - BiosMemoryMap[Index] = BiosMemoryMap[Index+1]; - BiosMemoryMap[Index+1] = TempMapItem; - } - } - } + MEMORY_DESCRIPTOR* MemoryDescriptor = NULL; + ULONG PageLookupTableSize; + ULONG PageLookupTablePages; + ULONG PageLookupTableStartPage = 0; + PVOID PageLookupTableMemAddress = NULL; + + // + // Calculate how much pages we need to keep the page lookup table + // + PageLookupTableSize = TotalPageCount * sizeof(PAGE_LOOKUP_TABLE_ITEM); + PageLookupTablePages = PageLookupTableSize / MM_PAGE_SIZE; + + // + // Search the highest memory block big enough to contain lookup table + // + while ((MemoryDescriptor = ArcGetMemoryDescriptor(MemoryDescriptor)) != NULL) + { + // + // Is it suitable memory? + // + if (MemoryDescriptor->MemoryType != MemoryFree) + { + // + // No. Process next descriptor + // + continue; + } + + // + // Is the block big enough? + // + if (MemoryDescriptor->PageCount < PageLookupTablePages) + { + // + // No. Process next descriptor + // + continue; + } + + // + // Is it at a higher address than previous suitable address? + // + if (MemoryDescriptor->BasePage < PageLookupTableStartPage) + { + // + // No. Process next descriptor + // + continue; + } + + // + // Memory block is more suitable than the previous one + // + PageLookupTableStartPage = MemoryDescriptor->BasePage; + PageLookupTableMemAddress = (PVOID)((ULONG_PTR) + (MemoryDescriptor->BasePage + MemoryDescriptor->PageCount) * MM_PAGE_SIZE + - PageLookupTableSize); + } + + DPRINTM(DPRINT_MEMORY, "MmFindLocationForPageLookupTable() returning 0x%x\n", PageLookupTableMemAddress); + + return PageLookupTableMemAddress; } -VOID MmInitPageLookupTable(PVOID PageLookupTable, ULONG TotalPageCount, PBIOS_MEMORY_MAP BiosMemoryMap, ULONG MapCount) +VOID MmInitPageLookupTable(PVOID PageLookupTable, ULONG TotalPageCount) { - ULONG MemoryMapStartPage; - ULONG MemoryMapEndPage; - ULONG MemoryMapPageCount; - ULONG MemoryMapPageAllocated; - ULONG PageLookupTableStartPage; - ULONG PageLookupTablePageCount; - ULONG Index; - - DbgPrint((DPRINT_MEMORY, "MmInitPageLookupTable()\n")); - - // 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, LoaderFirmwarePermanent); - - for (Index=0; IndexMemoryType) + { + case MemoryFree: + { + // + // Allocatable memory + // + MemoryMapPageAllocated = LoaderFree; + break; + } + case MemoryFirmwarePermanent: + { + // + // Firmware permanent memory + // + MemoryMapPageAllocated = LoaderFirmwarePermanent; + break; + } + case MemoryFirmwareTemporary: + { + // + // Firmware temporary memory + // + MemoryMapPageAllocated = LoaderFirmwareTemporary; + break; + } + case MemoryLoadedProgram: + { + // + // Bootloader code + // + MemoryMapPageAllocated = LoaderLoadedProgram; + break; + } + case MemorySpecialMemory: + { + // + // Special reserved memory + // + MemoryMapPageAllocated = LoaderSpecialMemory; + break; + } + default: + { + // + // Put something sensible here, which won't be overwritten + // + MemoryMapPageAllocated = LoaderSpecialMemory; + break; + } + } + + // + // Mark used pages in the lookup table + // + DPRINTM(DPRINT_MEMORY, "Marking pages as type %d: StartPage: %d PageCount: %d\n", MemoryMapPageAllocated, MemoryDescriptor->BasePage, MemoryDescriptor->PageCount); + MmMarkPagesInLookupTable(PageLookupTable, MemoryDescriptor->BasePage, MemoryDescriptor->PageCount, MemoryMapPageAllocated); + } + + // + // 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; + DPRINTM(DPRINT_MEMORY, "Marking the page lookup table pages as reserved StartPage: %d PageCount: %d\n", PageLookupTableStartPage, PageLookupTablePageCount); + MmMarkPagesInLookupTable(PageLookupTable, PageLookupTableStartPage, PageLookupTablePageCount, LoaderFirmwareTemporary); } VOID MmMarkPagesInLookupTable(PVOID PageLookupTable, ULONG StartPage, ULONG PageCount, TYPE_OF_MEMORY PageAllocated) @@ -343,13 +348,13 @@ VOID MmMarkPagesInLookupTable(PVOID PageLookupTable, ULONG StartPage, ULONG Page #if 0 if ((Index <= (StartPage + 16)) || (Index >= (StartPage+PageCount-16))) { - DbgPrint((DPRINT_MEMORY, "Index = %d StartPage = %d PageCount = %d\n", Index, StartPage, PageCount)); + DPRINTM(DPRINT_MEMORY, "Index = %d StartPage = %d PageCount = %d\n", Index, StartPage, PageCount); } #endif RealPageLookupTable[Index].PageAllocated = PageAllocated; RealPageLookupTable[Index].PageAllocationLength = (PageAllocated != LoaderFree) ? 1 : 0; } - DbgPrint((DPRINT_MEMORY, "MmMarkPagesInLookupTable() Done\n")); + DPRINTM(DPRINT_MEMORY, "MmMarkPagesInLookupTable() Done\n"); } VOID MmAllocatePagesInLookupTable(PVOID PageLookupTable, ULONG StartPage, ULONG PageCount, TYPE_OF_MEMORY MemoryType) @@ -417,7 +422,7 @@ ULONG MmFindAvailablePages(PVOID PageLookupTable, ULONG TotalPageCount, ULONG Pa } else { - DbgPrint((DPRINT_MEMORY, "Alloc low memory, LastFreePageHint %d, TPC %d\n", LastFreePageHint, TotalPageCount)); + DPRINTM(DPRINT_MEMORY, "Alloc low memory, LastFreePageHint %d, TPC %d\n", LastFreePageHint, TotalPageCount); /* Allocate "low" pages */ for (Index=1; Index < LastFreePageHint; Index++) { @@ -474,30 +479,6 @@ ULONG MmFindAvailablePagesBeforePage(PVOID PageLookupTable, ULONG TotalPageCount return 0; } -VOID MmFixupSystemMemoryMap(PBIOS_MEMORY_MAP BiosMemoryMap, ULONG* MapCount) -{ - UINT Index; - UINT Index2; - - // Loop through each entry in the array - for (Index=0; Index<*MapCount; Index++) - { - // 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 != BiosMemoryUsable) - { - // Slide every entry after this down one - for (Index2=Index; Index2<(*MapCount - 1); Index2++) - { - BiosMemoryMap[Index2] = BiosMemoryMap[Index2 + 1]; - } - (*MapCount)--; - Index--; - } - } -} - VOID MmUpdateLastFreePageHint(PVOID PageLookupTable, ULONG TotalPageCount) { PPAGE_LOOKUP_TABLE_ITEM RealPageLookupTable = (PPAGE_LOOKUP_TABLE_ITEM)PageLookupTable;