diff --git a/reactos/boot/freeldr/freeldr/arch/amd64/hwacpi.c b/reactos/boot/freeldr/freeldr/arch/amd64/hwacpi.c index 39f163ea4d2..cc7cdcd19af 100644 --- a/reactos/boot/freeldr/freeldr/arch/amd64/hwacpi.c +++ b/reactos/boot/freeldr/freeldr/arch/amd64/hwacpi.c @@ -1,130 +1,5 @@ -/* - * FreeLoader - * - * Copyright (C) 2004 Eric Kohl - * - * 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 - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * 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. - */ +/* No need to duplicate code ; import the i386 version */ -#include -#include - -BOOLEAN AcpiPresent = FALSE; - -static PRSDP_DESCRIPTOR -FindAcpiBios(VOID) -{ - PUCHAR Ptr; - - /* Find the 'Root System Descriptor Table Pointer' */ - Ptr = (PUCHAR)0xE0000; - while ((ULONG_PTR)Ptr < 0x100000) - { - if (!memcmp(Ptr, "RSD PTR ", 8)) - { - DbgPrint((DPRINT_HWDETECT, "ACPI supported\n")); - - return (PRSDP_DESCRIPTOR)Ptr; - } - - Ptr = (PUCHAR)((ULONG_PTR)Ptr + 0x10); - } - - DbgPrint((DPRINT_HWDETECT, "ACPI not supported\n")); - - return NULL; -} - - -VOID -DetectAcpiBios(PCONFIGURATION_COMPONENT_DATA SystemKey, ULONG *BusNumber) -{ - PCONFIGURATION_COMPONENT_DATA BiosKey; - PCM_PARTIAL_RESOURCE_LIST PartialResourceList; - PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptor; - PRSDP_DESCRIPTOR Rsdp; - PACPI_BIOS_DATA AcpiBiosData; - BIOS_MEMORY_MAP BiosMemoryMap[32]; - ULONG BiosMemoryMapEntryCount, TableSize; - - Rsdp = FindAcpiBios(); - - if (Rsdp) - { - /* Set up the flag in the loader block */ - AcpiPresent = TRUE; - LoaderBlock.Flags |= MB_FLAGS_ACPI_TABLE; - - /* Create new bus key */ - FldrCreateComponentKey(SystemKey, - L"MultifunctionAdapter", - *BusNumber, - AdapterClass, - MultiFunctionAdapter, - &BiosKey); - - /* Set 'Component Information' */ - FldrSetComponentInformation(BiosKey, - 0x0, - 0x0, - 0xFFFFFFFF); - - /* Get BIOS memory map */ - RtlZeroMemory(BiosMemoryMap, sizeof(BIOS_MEMORY_MAP) * 32); - BiosMemoryMapEntryCount = MachGetMemoryMap(BiosMemoryMap, - sizeof(BiosMemoryMap) / sizeof(BIOS_MEMORY_MAP)); - - /* Calculate the table size */ - TableSize = BiosMemoryMapEntryCount * sizeof(BIOS_MEMORY_MAP) + - sizeof(ACPI_BIOS_DATA) - sizeof(BIOS_MEMORY_MAP); - - /* Set 'Configuration Data' value */ - PartialResourceList = - MmHeapAlloc(sizeof(CM_PARTIAL_RESOURCE_LIST) + TableSize); - memset(PartialResourceList, 0, sizeof(CM_PARTIAL_RESOURCE_LIST) + TableSize); - PartialResourceList->Version = 0; - PartialResourceList->Revision = 0; - PartialResourceList->Count = 1; - - PartialDescriptor = &PartialResourceList->PartialDescriptors[0]; - PartialDescriptor->Type = CmResourceTypeDeviceSpecific; - PartialDescriptor->ShareDisposition = CmResourceShareUndetermined; - PartialDescriptor->u.DeviceSpecificData.DataSize = TableSize; - - /* Fill the table */ - AcpiBiosData = (PACPI_BIOS_DATA)&PartialResourceList->PartialDescriptors[1]; - AcpiBiosData->RSDTAddress.LowPart = Rsdp->rsdt_physical_address; - AcpiBiosData->Count = BiosMemoryMapEntryCount; - memcpy(AcpiBiosData->MemoryMap, BiosMemoryMap, - BiosMemoryMapEntryCount * sizeof(BIOS_MEMORY_MAP)); - - DbgPrint((DPRINT_HWDETECT, "RSDT %p, data size %x\n", Rsdp->rsdt_physical_address, - TableSize)); - - FldrSetConfigurationData(BiosKey, - PartialResourceList, - sizeof(CM_PARTIAL_RESOURCE_LIST) + TableSize - ); - - /* Increment bus number */ - (*BusNumber)++; - - /* Set 'Identifier' value */ - FldrSetIdentifier(BiosKey, "ACPI BIOS"); - MmFreeMemory(PartialResourceList); - } -} +#include "../i386/hwacpi.c" /* EOF */ diff --git a/reactos/boot/freeldr/freeldr/arch/i386/hwacpi.c b/reactos/boot/freeldr/freeldr/arch/i386/hwacpi.c index c0740f57f71..a578b8ff70e 100644 --- a/reactos/boot/freeldr/freeldr/arch/i386/hwacpi.c +++ b/reactos/boot/freeldr/freeldr/arch/i386/hwacpi.c @@ -83,7 +83,7 @@ DetectAcpiBios(PCONFIGURATION_COMPONENT_DATA SystemKey, ULONG *BusNumber) /* Get BIOS memory map */ RtlZeroMemory(BiosMemoryMap, sizeof(BIOS_MEMORY_MAP) * 32); - BiosMemoryMapEntryCount = MachGetMemoryMap(BiosMemoryMap, + BiosMemoryMapEntryCount = PcMemGetMemoryMap(BiosMemoryMap, sizeof(BiosMemoryMap) / sizeof(BIOS_MEMORY_MAP)); /* Calculate the table size */ diff --git a/reactos/boot/freeldr/freeldr/include/machine.h b/reactos/boot/freeldr/freeldr/include/machine.h index b117319544d..94c737391b9 100644 --- a/reactos/boot/freeldr/freeldr/include/machine.h +++ b/reactos/boot/freeldr/freeldr/include/machine.h @@ -59,6 +59,7 @@ typedef struct tagMACHVTBL VOID (*Beep)(VOID); VOID (*PrepareForReactOS)(IN BOOLEAN Setup); + MEMORY_DESCRIPTOR* (*GetMemoryDescriptor)(MEMORY_DESCRIPTOR* Current); ULONG (*GetMemoryMap)(PBIOS_MEMORY_MAP BiosMemoryMap, ULONG MaxMemoryMapSize); BOOLEAN (*DiskGetBootVolume)(PULONG DriveNumber, PULONGLONG StartSector, PULONGLONG SectorCount, int *FsType); @@ -98,7 +99,7 @@ VOID MachVideoSetPaletteColor(UCHAR Color, UCHAR Red, UCHAR Green, UCHAR Blue); VOID MachVideoGetPaletteColor(UCHAR Color, UCHAR *Red, UCHAR *Green, UCHAR *Blue); VOID MachVideoSync(VOID); VOID MachBeep(VOID); -ULONG MachGetMemoryMap(PBIOS_MEMORY_MAP BiosMemoryMap, ULONG MaxMemoryMapSize); +MEMORY_DESCRIPTOR* ArcGetMemoryDescriptor(MEMORY_DESCRIPTOR* Current); BOOLEAN MachDiskGetBootVolume(PULONG DriveNumber, PULONGLONG StartSector, PULONGLONG SectorCount, int *FsType); BOOLEAN MachDiskGetSystemVolume(char *SystemPath, @@ -138,7 +139,6 @@ VOID MachPrepareForReactOS(IN BOOLEAN Setup); #define MachVideoSync() MachVtbl.VideoSync() #define MachBeep() MachVtbl.Beep() #define MachPrepareForReactOS(a) MachVtbl.PrepareForReactOS(a) -#define MachGetMemoryMap(MMap, Size) MachVtbl.GetMemoryMap((MMap), (Size)) #define MachDiskGetBootVolume(Drv, Start, Cnt, FsType) MachVtbl.DiskGetBootVolume((Drv), (Start), (Cnt), (FsType)) #define MachDiskGetSystemVolume(SysPath, RemPath, Dev, Drv, Start, Cnt, FsType) MachVtbl.DiskGetSystemVolume((SysPath), (RemPath), (Dev), (Drv), (Start), (Cnt), (FsType)) #define MachDiskGetBootPath(Path, Size) MachVtbl.DiskGetBootPath((Path), (Size)) diff --git a/reactos/boot/freeldr/freeldr/include/mm.h b/reactos/boot/freeldr/freeldr/include/mm.h index 6ee257d186b..9e8b8df29a3 100644 --- a/reactos/boot/freeldr/freeldr/include/mm.h +++ b/reactos/boot/freeldr/freeldr/include/mm.h @@ -88,21 +88,18 @@ extern ULONG FreePagesInLookupTable; extern ULONG LastFreePageHint; #ifdef DBG -PUCHAR MmGetSystemMemoryMapTypeString(ULONG Type); +PCSTR MmGetSystemMemoryMapTypeString(MEMORY_TYPE Type); #endif ULONG MmGetPageNumberFromAddress(PVOID Address); // Returns the page number that contains a linear address -PVOID MmGetEndAddressOfAnyMemory(PBIOS_MEMORY_MAP BiosMemoryMap, ULONG MapCount); // Returns the last address of memory from the memory map -ULONG MmGetAddressablePageCountIncludingHoles(PBIOS_MEMORY_MAP BiosMemoryMap, ULONG MapCount); // Returns the count of addressable pages from address zero including any memory holes and reserved memory regions -PVOID MmFindLocationForPageLookupTable(PBIOS_MEMORY_MAP BiosMemoryMap, ULONG MapCount); // Returns the address for a memory chunk big enough to hold the page lookup table (starts search from end of memory) -VOID MmSortBiosMemoryMap(PBIOS_MEMORY_MAP BiosMemoryMap, ULONG MapCount); // Sorts the BIOS_MEMORY_MAP array so the first element corresponds to the first address in memory -VOID MmInitPageLookupTable(PVOID PageLookupTable, ULONG TotalPageCount, PBIOS_MEMORY_MAP BiosMemoryMap, ULONG MapCount); // Inits the page lookup table according to the memory types in the memory map +ULONG MmGetAddressablePageCountIncludingHoles(VOID); // Returns the count of addressable pages from address zero including any memory holes and reserved memory regions +PVOID MmFindLocationForPageLookupTable(ULONG TotalPageCount); // Returns the address for a memory chunk big enough to hold the page lookup table (starts search from end of memory) +VOID MmInitPageLookupTable(PVOID PageLookupTable, ULONG TotalPageCount); // Inits the page lookup table according to the memory types in the memory map VOID MmMarkPagesInLookupTable(PVOID PageLookupTable, ULONG StartPage, ULONG PageCount, TYPE_OF_MEMORY PageAllocated); // Marks the specified pages as allocated or free in the lookup table VOID MmAllocatePagesInLookupTable(PVOID PageLookupTable, ULONG StartPage, ULONG PageCount, TYPE_OF_MEMORY MemoryType); // Allocates the specified pages in the lookup table ULONG MmCountFreePagesInLookupTable(PVOID PageLookupTable, ULONG TotalPageCount); // Returns the number of free pages in the lookup table ULONG MmFindAvailablePages(PVOID PageLookupTable, ULONG TotalPageCount, ULONG PagesNeeded, BOOLEAN FromEnd); // Returns the page number of the first available page range from the beginning or end of memory ULONG MmFindAvailablePagesBeforePage(PVOID PageLookupTable, ULONG TotalPageCount, ULONG PagesNeeded, ULONG LastPage); // Returns the page number of the first available page range before the specified page -VOID MmFixupSystemMemoryMap(PBIOS_MEMORY_MAP BiosMemoryMap, ULONG* MapCount); // Removes entries in the memory map that describe memory above 4G VOID MmUpdateLastFreePageHint(PVOID PageLookupTable, ULONG TotalPageCount); // Sets the LastFreePageHint to the last usable page of memory BOOLEAN MmAreMemoryPagesAvailable(PVOID PageLookupTable, ULONG TotalPageCount, PVOID PageAddress, ULONG PageCount); // Returns TRUE if the specified pages of memory are available, otherwise FALSE VOID MmSetMemoryType(PVOID MemoryAddress, ULONG MemorySize, TYPE_OF_MEMORY NewType); // Use with EXTREME caution! diff --git a/reactos/boot/freeldr/freeldr/machine.c b/reactos/boot/freeldr/freeldr/machine.c index 54b8e1f50cd..f813d2aa9bd 100644 --- a/reactos/boot/freeldr/freeldr/machine.c +++ b/reactos/boot/freeldr/freeldr/machine.c @@ -36,7 +36,6 @@ #undef MachVideoSync #undef MachBeep #undef MachPrepareForReactOS -#undef MachGetMemoryMap #undef MachDiskGetBootVolume #undef MachDiskGetSystemVolume #undef MachDiskGetBootPath @@ -153,10 +152,176 @@ MachPrepareForReactOS(IN BOOLEAN Setup) MachVtbl.PrepareForReactOS(Setup); } -ULONG -MachGetMemoryMap(PBIOS_MEMORY_MAP BiosMemoryMap, ULONG MaxMemoryMapSize) +typedef struct { - return MachVtbl.GetMemoryMap(BiosMemoryMap, MaxMemoryMapSize); + 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__ + { { MemoryFirmwarePermanent, 0x00, 1 }, 0, }, // arm exception handlers + { { MemoryFirmwareTemporary, 0x01, 7 }, 1, }, // arm board block + freeldr stack + cmdline + { { MemoryLoadedProgram, 0x08, 0x70 }, 2, }, // freeldr image (roughly max. 0x64 pages) +#endif +}; +MEMORY_DESCRIPTOR* +ArcGetMemoryDescriptor(MEMORY_DESCRIPTOR* Current) +{ + MEMORY_DESCRIPTOR_INT* CurrentDescriptor; + BIOS_MEMORY_MAP BiosMemoryMap[32]; + static ULONG BiosMemoryMapEntryCount; + static MEMORY_DESCRIPTOR_INT BiosMemoryDescriptors[32]; + static BOOLEAN MemoryMapInitialized = FALSE; + ULONG i, j; + + // + // Does machine provide an override for this function? + // + if (MachVtbl.GetMemoryDescriptor) + { + // + // Yes. Use it instead + // + return MachVtbl.GetMemoryDescriptor(Current); + } + + // + // Check if it is the first time we're called + // + if (!MemoryMapInitialized) + { + // + // Get the machine generated memory map + // + RtlZeroMemory(BiosMemoryMap, sizeof(BIOS_MEMORY_MAP) * 32); + BiosMemoryMapEntryCount = MachVtbl.GetMemoryMap(BiosMemoryMap, + sizeof(BiosMemoryMap) / sizeof(BIOS_MEMORY_MAP)); + + // + // 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 = BiosMemoryMap[i].BaseAddress / MM_PAGE_SIZE; + BiosMemoryDescriptors[j].m.PageCount = 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 (MEMORY_DESCRIPTOR*)&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 (MEMORY_DESCRIPTOR*)&MemoryDescriptors[0].m; + } + else + { + // + // No fixed memory descriptor; end of memory map + // + return NULL; + } + } + else + { + // + // Current entry is a fixed descriptor + // + if (CurrentDescriptor->Index + 1 < sizeof(MemoryDescriptors) / sizeof(MemoryDescriptors[0])) + { + // + // Return next fixed descriptor + // + return (MEMORY_DESCRIPTOR*)&MemoryDescriptors[CurrentDescriptor->Index + 1].m; + } + else + { + // + // No more fixed memory descriptor; end of memory map + // + return NULL; + } + } } BOOLEAN diff --git a/reactos/boot/freeldr/freeldr/mm/meminit.c b/reactos/boot/freeldr/freeldr/mm/meminit.c index 8cc518f6d4d..7921970f913 100644 --- a/reactos/boot/freeldr/freeldr/mm/meminit.c +++ b/reactos/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 @@ -23,19 +24,24 @@ #ifdef 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; + MEMORY_DESCRIPTOR* MemoryDescriptor = NULL; #endif DPRINTM(DPRINT_MEMORY, "Initializing Memory Manager.\n"); - RtlZeroMemory(BiosMemoryMap, sizeof(BIOS_MEMORY_MAP) * 32); - - BiosMemoryMapEntryCount = MachGetMemoryMap(BiosMemoryMap, sizeof(BiosMemoryMap) / sizeof(BIOS_MEMORY_MAP)); - #ifdef 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) { - DPRINTM(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,25 +87,9 @@ BOOLEAN MmInitializeMemoryManager(VOID) } // Initialize the page lookup table - MmInitPageLookupTable(PageLookupTableAddress, TotalPagesInLookupTable, BiosMemoryMap, BiosMemoryMapEntryCount); + MmInitPageLookupTable(PageLookupTableAddress, TotalPagesInLookupTable); MmUpdateLastFreePageHint(PageLookupTableAddress, TotalPagesInLookupTable); - // Add machine-dependent stuff -#if defined (__i386__) || defined (_M_AMD64) - 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); @@ -151,7 +129,7 @@ VOID MmInitializeHeap(PVOID PageLookupTable) } #ifdef DBG -PUCHAR MmGetSystemMemoryMapTypeString(ULONG Type) +PCSTR MmGetSystemMemoryMapTypeString(MEMORY_TYPE Type) { ULONG Index; @@ -172,165 +150,157 @@ 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; + MEMORY_DESCRIPTOR* MemoryDescriptor = NULL; + ULONG EndPage = 0; - MaxStartAddressSoFar = 0; - EndAddressOfMemory = 0; - for (Index=0; Index 0xFFFFFFFF) - { - EndAddressOfMemory = 0xFFFFFFFF; - } - } - } + // + // 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, "MmGetEndAddressOfAnyMemory() returning 0x%x\n", (ULONG)EndAddressOfMemory); + DPRINTM(DPRINT_MEMORY, "MmGetAddressablePageCountIncludingHoles() returning 0x%x\n", EndPage); - return (PVOID)(ULONG_PTR)EndAddressOfMemory; + return EndPage; } -ULONG MmGetAddressablePageCountIncludingHoles(PBIOS_MEMORY_MAP BiosMemoryMap, ULONG MapCount) +PVOID MmFindLocationForPageLookupTable(ULONG TotalPageCount) { - ULONG PageCount; - ULONGLONG EndAddress; + MEMORY_DESCRIPTOR* MemoryDescriptor = NULL; + ULONG PageLookupTableSize; + ULONG PageLookupTablePages; + ULONG PageLookupTableStartPage = 0; + PVOID PageLookupTableMemAddress = NULL; - EndAddress = (ULONGLONG)(ULONG_PTR)MmGetEndAddressOfAnyMemory(BiosMemoryMap, MapCount); + // + // Calculate how much pages we need to keep the page lookup table + // + PageLookupTableSize = TotalPageCount * sizeof(PAGE_LOOKUP_TABLE_ITEM); + PageLookupTablePages = PageLookupTableSize / MM_PAGE_SIZE; - // 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; + // + // 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; + } - DPRINTM(DPRINT_MEMORY, "MmGetEndAddressOfAnyMemory() returned 0xFFFFFFFF, correcting to be 0x100000000.\n"); - } + // + // Is the block big enough? + // + if (MemoryDescriptor->PageCount < PageLookupTablePages) + { + // + // No. Process next descriptor + // + continue; + } - PageCount = (EndAddress / MM_PAGE_SIZE); + // + // Is it at a higher address than previous suitable address? + // + if (MemoryDescriptor->BasePage < PageLookupTableStartPage) + { + // + // No. Process next descriptor + // + continue; + } - DPRINTM(DPRINT_MEMORY, "MmGetAddressablePageCountIncludingHoles() returning %d\n", PageCount); + // + // Memory block is more suitable than the previous one + // + PageLookupTableStartPage = MemoryDescriptor->BasePage; + PageLookupTableMemAddress = (PVOID)((ULONG_PTR) + (MemoryDescriptor->BasePage + MemoryDescriptor->PageCount) * MM_PAGE_SIZE + - PageLookupTableSize); + } - return PageCount; + DPRINTM(DPRINT_MEMORY, "MmFindLocationForPageLookupTable() returning 0x%x\n", PageLookupTableMemAddress); + + return PageLookupTableMemAddress; } -PVOID MmFindLocationForPageLookupTable(PBIOS_MEMORY_MAP BiosMemoryMap, ULONG MapCount) +VOID MmInitPageLookupTable(PVOID PageLookupTable, ULONG TotalPageCount) { - ULONG TotalPageCount; - ULONG PageLookupTableSize; - PVOID PageLookupTableMemAddress; - int Index; - BIOS_MEMORY_MAP TempBiosMemoryMap[32]; + MEMORY_DESCRIPTOR* MemoryDescriptor = NULL; + TYPE_OF_MEMORY MemoryMapPageAllocated; + ULONG PageLookupTableStartPage; + ULONG PageLookupTablePageCount; - TotalPageCount = MmGetAddressablePageCountIncludingHoles(BiosMemoryMap, MapCount); - PageLookupTableSize = TotalPageCount * sizeof(PAGE_LOOKUP_TABLE_ITEM); - PageLookupTableMemAddress = 0; + DPRINTM(DPRINT_MEMORY, "MmInitPageLookupTable()\n"); - RtlCopyMemory(TempBiosMemoryMap, BiosMemoryMap, sizeof(BIOS_MEMORY_MAP) * 32); - MmSortBiosMemoryMap(TempBiosMemoryMap, MapCount); + // + // 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); - // 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 + // + // Parse the whole memory map + // + while ((MemoryDescriptor = ArcGetMemoryDescriptor(MemoryDescriptor)) != NULL) + { + // + // Convert ARC memory type to loader memory type + // + switch (MemoryDescriptor->MemoryType) + { + case MemoryFree: + { + // + // Allocatable memory + // + MemoryMapPageAllocated = LoaderFree; + break; + } + default: + { + // + // Put something sensible here, which won't be overwritten + // + MemoryMapPageAllocated = LoaderSpecialMemory; + break; + } + } - // skip if this is not usable region - if (TempBiosMemoryMap[Index].Type != BiosMemoryUsable) - continue; + // + // 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); + } - if (TempBiosMemoryMap[Index].Length >= PageLookupTableSize) - { - PageLookupTableMemAddress = (PVOID)(ULONG_PTR) - (TempBiosMemoryMap[Index].BaseAddress + (TempBiosMemoryMap[Index].Length - PageLookupTableSize)); - break; - } - } - - DPRINTM(DPRINT_MEMORY, "MmFindLocationForPageLookupTable() returning 0x%x\n", PageLookupTableMemAddress); - - return PageLookupTableMemAddress; -} - -VOID MmSortBiosMemoryMap(PBIOS_MEMORY_MAP BiosMemoryMap, ULONG MapCount) -{ - 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; - } - } - } -} - -VOID MmInitPageLookupTable(PVOID PageLookupTable, ULONG TotalPageCount, PBIOS_MEMORY_MAP BiosMemoryMap, ULONG MapCount) -{ - ULONG MemoryMapStartPage; - ULONG MemoryMapEndPage; - ULONG MemoryMapPageCount; - ULONG MemoryMapPageAllocated; - ULONG PageLookupTableStartPage; - ULONG PageLookupTablePageCount; - ULONG Index; - - DPRINTM(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; Index