Remove MachGetMemoryMap() and replace it by ArcGetMemoryDescriptor(). Rework memory initialization to use it.

As a bonus, we're not limited anymore to 32 memory descriptors, and having more than 4GB of RAM doesn't lead to out of bounds accesses

svn path=/trunk/; revision=40710
This commit is contained in:
Hervé Poussineau 2009-04-26 20:22:16 +00:00
parent 5ce8637a17
commit 54a86cf16f
9 changed files with 337 additions and 354 deletions

View file

@ -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 <freeldr.h>
#include <debug.h>
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 */

View file

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

View file

@ -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))

View file

@ -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!

View file

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

View file

@ -1,6 +1,7 @@
/*
* FreeLoader
* Copyright (C) 2006-2008 Aleksey Bragin <aleksey@reactos.org>
* Copyright (C) 2006-2009 Hervé Poussineau <hpoussin@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
@ -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; Index<BiosMemoryMapEntryCount; Index++)
{
DPRINTM(DPRINT_MEMORY, "%x%x\t %x%x\t %s\n", BiosMemoryMap[Index].BaseAddress, BiosMemoryMap[Index].Length, MmGetSystemMemoryMapTypeString(BiosMemoryMap[Index].Type));
}
DPRINTM(DPRINT_MEMORY, "%x\t %x\t %s\n",
MemoryDescriptor->BasePage * 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<MapCount; Index++)
{
if (MaxStartAddressSoFar <= BiosMemoryMap[Index].BaseAddress)
{
MaxStartAddressSoFar = BiosMemoryMap[Index].BaseAddress;
EndAddressOfMemory = (MaxStartAddressSoFar + BiosMemoryMap[Index].Length);
if (EndAddressOfMemory > 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<MapCount; Index++)
{
MemoryMapStartPage = MmGetPageNumberFromAddress((PVOID)(ULONG_PTR)BiosMemoryMap[Index].BaseAddress);
MemoryMapEndPage = MmGetPageNumberFromAddress((PVOID)(ULONG_PTR)(BiosMemoryMap[Index].BaseAddress + BiosMemoryMap[Index].Length - 1));
MemoryMapPageCount = (MemoryMapEndPage - MemoryMapStartPage) + 1;
switch (BiosMemoryMap[Index].Type)
{
case BiosMemoryUsable:
MemoryMapPageAllocated = LoaderFree;
break;
case BiosMemoryAcpiReclaim:
case BiosMemoryAcpiNvs:
MemoryMapPageAllocated = LoaderSpecialMemory;
break;
default:
MemoryMapPageAllocated = LoaderSpecialMemory;
}
DPRINTM(DPRINT_MEMORY, "Marking pages as type %d: StartPage: %d PageCount: %d\n", MemoryMapPageAllocated, MemoryMapStartPage, MemoryMapPageCount);
MmMarkPagesInLookupTable(PageLookupTable, MemoryMapStartPage, MemoryMapPageCount, 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);
//
// 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)
@ -474,30 +444,6 @@ ULONG MmFindAvailablePagesBeforePage(PVOID PageLookupTable, ULONG TotalPageCount
return 0;
}
VOID MmFixupSystemMemoryMap(PBIOS_MEMORY_MAP BiosMemoryMap, ULONG* MapCount)
{
UINT32 Index;
UINT32 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;

View file

@ -642,7 +642,7 @@ LoadAndBootReactOS(PCSTR OperatingSystemName)
LoaderBlock.DrivesAddr = reactos_arc_disk_info;
LoaderBlock.RdAddr = (ULONG_PTR)gRamDiskBase;
LoaderBlock.RdLength = gRamDiskSize;
LoaderBlock.MmapLength = (SIZE_T)MachGetMemoryMap((PBIOS_MEMORY_MAP)reactos_memory_map, 32) * sizeof(memory_map_t);
LoaderBlock.MmapLength = (SIZE_T)MachVtbl.GetMemoryMap((PBIOS_MEMORY_MAP)reactos_memory_map, 32) * sizeof(memory_map_t);
if (LoaderBlock.MmapLength)
{
ULONG i;

View file

@ -72,7 +72,7 @@ VOID LoadReactOSSetup(VOID)
LoaderBlock.PageDirectoryEnd = (ULONG_PTR)&PageDirectoryEnd;
LoaderBlock.ModsCount = 0;
LoaderBlock.ModsAddr = reactos_modules;
LoaderBlock.MmapLength = (unsigned long)MachGetMemoryMap((PBIOS_MEMORY_MAP)reactos_memory_map, 32) * sizeof(memory_map_t);
LoaderBlock.MmapLength = (unsigned long)MachVtbl.GetMemoryMap((PBIOS_MEMORY_MAP)reactos_memory_map, 32) * sizeof(memory_map_t);
if (LoaderBlock.MmapLength)
{
#if defined (_M_IX86) || defined (_M_AMD64)

View file

@ -269,7 +269,7 @@ WinLdrLoadImage(IN PCHAR FileName,
CHAR ProgressString[256];
/* Inform user we are loading files */
sprintf(ProgressString, "Loading %s...", FileName);
sprintf(ProgressString, "Loading %s...", strchr(FileName, '\\') + 1);
UiDrawProgressBarCenter(1, 100, ProgressString);
/* Open the image file */