mirror of
https://github.com/reactos/reactos.git
synced 2025-04-26 08:30:21 +00:00
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:
parent
5ce8637a17
commit
54a86cf16f
9 changed files with 337 additions and 354 deletions
|
@ -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 */
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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!
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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[] =
|
||||
{
|
||||
{ 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");
|
||||
for (Index=0; Index<BiosMemoryMapEntryCount; Index++)
|
||||
while ((MemoryDescriptor = ArcGetMemoryDescriptor(MemoryDescriptor)) != NULL)
|
||||
{
|
||||
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,90 +150,92 @@ 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++)
|
||||
//
|
||||
// Go through the whole memory map to get max address
|
||||
//
|
||||
while ((MemoryDescriptor = ArcGetMemoryDescriptor(MemoryDescriptor)) != NULL)
|
||||
{
|
||||
if (MaxStartAddressSoFar <= BiosMemoryMap[Index].BaseAddress)
|
||||
//
|
||||
// Check if we got a higher end page address
|
||||
//
|
||||
if (MemoryDescriptor->BasePage + MemoryDescriptor->PageCount > EndPage)
|
||||
{
|
||||
MaxStartAddressSoFar = BiosMemoryMap[Index].BaseAddress;
|
||||
EndAddressOfMemory = (MaxStartAddressSoFar + BiosMemoryMap[Index].Length);
|
||||
if (EndAddressOfMemory > 0xFFFFFFFF)
|
||||
{
|
||||
EndAddressOfMemory = 0xFFFFFFFF;
|
||||
//
|
||||
// Yes, remember it
|
||||
//
|
||||
EndPage = MemoryDescriptor->BasePage + MemoryDescriptor->PageCount;
|
||||
}
|
||||
}
|
||||
|
||||
DPRINTM(DPRINT_MEMORY, "MmGetAddressablePageCountIncludingHoles() returning 0x%x\n", EndPage);
|
||||
|
||||
return EndPage;
|
||||
}
|
||||
|
||||
DPRINTM(DPRINT_MEMORY, "MmGetEndAddressOfAnyMemory() returning 0x%x\n", (ULONG)EndAddressOfMemory);
|
||||
|
||||
return (PVOID)(ULONG_PTR)EndAddressOfMemory;
|
||||
}
|
||||
|
||||
ULONG MmGetAddressablePageCountIncludingHoles(PBIOS_MEMORY_MAP BiosMemoryMap, ULONG MapCount)
|
||||
PVOID MmFindLocationForPageLookupTable(ULONG TotalPageCount)
|
||||
{
|
||||
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;
|
||||
|
||||
DPRINTM(DPRINT_MEMORY, "MmGetEndAddressOfAnyMemory() returned 0xFFFFFFFF, correcting to be 0x100000000.\n");
|
||||
}
|
||||
|
||||
PageCount = (EndAddress / MM_PAGE_SIZE);
|
||||
|
||||
DPRINTM(DPRINT_MEMORY, "MmGetAddressablePageCountIncludingHoles() returning %d\n", PageCount);
|
||||
|
||||
return PageCount;
|
||||
}
|
||||
|
||||
PVOID MmFindLocationForPageLookupTable(PBIOS_MEMORY_MAP BiosMemoryMap, ULONG MapCount)
|
||||
{
|
||||
ULONG TotalPageCount;
|
||||
MEMORY_DESCRIPTOR* MemoryDescriptor = NULL;
|
||||
ULONG PageLookupTableSize;
|
||||
PVOID PageLookupTableMemAddress;
|
||||
int Index;
|
||||
BIOS_MEMORY_MAP TempBiosMemoryMap[32];
|
||||
ULONG PageLookupTablePages;
|
||||
ULONG PageLookupTableStartPage = 0;
|
||||
PVOID PageLookupTableMemAddress = NULL;
|
||||
|
||||
TotalPageCount = MmGetAddressablePageCountIncludingHoles(BiosMemoryMap, MapCount);
|
||||
//
|
||||
// Calculate how much pages we need to keep the page lookup table
|
||||
//
|
||||
PageLookupTableSize = TotalPageCount * sizeof(PAGE_LOOKUP_TABLE_ITEM);
|
||||
PageLookupTableMemAddress = 0;
|
||||
PageLookupTablePages = PageLookupTableSize / MM_PAGE_SIZE;
|
||||
|
||||
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--)
|
||||
//
|
||||
// Search the highest memory block big enough to contain lookup table
|
||||
//
|
||||
while ((MemoryDescriptor = ArcGetMemoryDescriptor(MemoryDescriptor)) != NULL)
|
||||
{
|
||||
// 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)
|
||||
//
|
||||
// Is it suitable memory?
|
||||
//
|
||||
if (MemoryDescriptor->MemoryType != MemoryFree)
|
||||
{
|
||||
//
|
||||
// No. Process next descriptor
|
||||
//
|
||||
continue;
|
||||
|
||||
if (TempBiosMemoryMap[Index].Length >= PageLookupTableSize)
|
||||
{
|
||||
PageLookupTableMemAddress = (PVOID)(ULONG_PTR)
|
||||
(TempBiosMemoryMap[Index].BaseAddress + (TempBiosMemoryMap[Index].Length - PageLookupTableSize));
|
||||
break;
|
||||
}
|
||||
|
||||
//
|
||||
// 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);
|
||||
|
@ -263,70 +243,60 @@ PVOID MmFindLocationForPageLookupTable(PBIOS_MEMORY_MAP BiosMemoryMap, ULONG Map
|
|||
return PageLookupTableMemAddress;
|
||||
}
|
||||
|
||||
VOID MmSortBiosMemoryMap(PBIOS_MEMORY_MAP BiosMemoryMap, ULONG MapCount)
|
||||
VOID MmInitPageLookupTable(PVOID PageLookupTable, 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
VOID MmInitPageLookupTable(PVOID PageLookupTable, ULONG TotalPageCount, PBIOS_MEMORY_MAP BiosMemoryMap, ULONG MapCount)
|
||||
{
|
||||
ULONG MemoryMapStartPage;
|
||||
ULONG MemoryMapEndPage;
|
||||
ULONG MemoryMapPageCount;
|
||||
ULONG MemoryMapPageAllocated;
|
||||
MEMORY_DESCRIPTOR* MemoryDescriptor = NULL;
|
||||
TYPE_OF_MEMORY 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++)
|
||||
//
|
||||
// Parse the whole memory map
|
||||
//
|
||||
while ((MemoryDescriptor = ArcGetMemoryDescriptor(MemoryDescriptor)) != NULL)
|
||||
{
|
||||
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)
|
||||
//
|
||||
// Convert ARC memory type to loader memory type
|
||||
//
|
||||
switch (MemoryDescriptor->MemoryType)
|
||||
{
|
||||
case BiosMemoryUsable:
|
||||
case MemoryFree:
|
||||
{
|
||||
//
|
||||
// Allocatable memory
|
||||
//
|
||||
MemoryMapPageAllocated = LoaderFree;
|
||||
break;
|
||||
|
||||
case BiosMemoryAcpiReclaim:
|
||||
case BiosMemoryAcpiNvs:
|
||||
}
|
||||
default:
|
||||
{
|
||||
//
|
||||
// Put something sensible here, which won't be overwritten
|
||||
//
|
||||
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 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);
|
||||
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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 */
|
||||
|
|
Loading…
Reference in a new issue