- Do not ignore BIOS memory map anymore. Private BIOS ranges (such as ACPI, SMBIOS, VideoROM, etc) are not assumed "free" anymore (which would result in hardware failure, crashes and/or corrupted memory).

- Enhance the FreeLDR 2 NTLDR Compatibility Layer:
 * Use a special routine for grabbing static memory descriptors, so that if we ever run out, we will bugcheck.
 * The descriptors need to contain physical addresses, not virtual. Do proper fixups to handle this.
 * Add a "Free" memory descriptor for all memory on the system. This needs to be fragmented later.
 * Add memory descriptors for each reserved entry in the BIOS memory map.
 * Add memory descriptors for the PDE and KPCR pages that FreeLDR allocates.
 * Add a memory descriptor for page 0, which is reserved.
 * Add a memory descriptor for the Video frame buffer at 0xA0000. This is the location on most systems, and also the location that ReactOS hard-codes in other Mm code.
- Bug found and NTLDR memory descriptor analysis by Alex.


svn path=/trunk/; revision=28537
This commit is contained in:
Aleksey Bragin 2007-08-25 09:38:13 +00:00
parent 9ec7d785cb
commit 37ae229f62
4 changed files with 178 additions and 19 deletions

View file

@ -599,7 +599,7 @@ LoadAndBootReactOS(PCSTR OperatingSystemName)
if (LoaderBlock.MmapLength)
{
ULONG i;
LoaderBlock.Flags |= MB_FLAGS_MEM_INFO | MB_FLAGS_MMAP_INFO;
LoaderBlock.MmapAddr = (unsigned long)&reactos_memory_map;
reactos_memory_map_descriptor_size = sizeof(memory_map_t); // GetBiosMemoryMap uses a fixed value of 24
for (i=0; i<(LoaderBlock.MmapLength/sizeof(memory_map_t)); i++)

View file

@ -23,6 +23,12 @@ ULONG MmFreeLdrPageDirectoryEnd;
/* FreeLDR Loader Data */
PROS_LOADER_PARAMETER_BLOCK KeRosLoaderBlock;
BOOLEAN AcpiTableDetected;
ADDRESS_RANGE KeMemoryMap[64];
ULONG KeMemoryMapRangeCount;
/* NT Loader Module/Descriptor Count */
ULONG BldrCurrentMd;
ULONG BldrCurrentMod;
/* NT Loader Data. Eats up about 80KB! */
LOADER_PARAMETER_BLOCK BldrLoaderBlock; // 0x0000
@ -45,6 +51,15 @@ ARC_DISK_SIGNATURE BldrDiskInfo[32]; // 0x1413C
/* FUNCTIONS *****************************************************************/
PMEMORY_ALLOCATION_DESCRIPTOR
NTAPI
KiRosGetMdFromArray(VOID)
{
/* Return the next MD from the list, but make sure we don't overflow */
if (BldrCurrentMd > 64) KEBUGCHECK(0);
return &BldrMemoryDescriptors[BldrCurrentMd++];
}
VOID
NTAPI
KiRosFrldrLpbToNtLpb(IN PROS_LOADER_PARAMETER_BLOCK RosLoaderBlock,
@ -69,6 +84,7 @@ KiRosFrldrLpbToNtLpb(IN PROS_LOADER_PARAMETER_BLOCK RosLoaderBlock,
AcpiTableDetected = (RosLoaderBlock->Flags & MB_FLAGS_ACPI_TABLE) ? TRUE : FALSE;
MmFreeLdrMemHigher = RosLoaderBlock->MemHigher;
MmFreeLdrPageDirectoryEnd = RosLoaderBlock->PageDirectoryEnd;
if (!MmFreeLdrPageDirectoryEnd) MmFreeLdrPageDirectoryEnd = 0x40000;
/* Set the NT Loader block and initialize it */
*NtLoaderBlock = LoaderBlock = &BldrLoaderBlock;
@ -89,6 +105,64 @@ KiRosFrldrLpbToNtLpb(IN PROS_LOADER_PARAMETER_BLOCK RosLoaderBlock,
InitializeListHead(&LoaderBlock->BootDriverListHead);
InitializeListHead(&LoaderBlock->ArcDiskInformation->DiskSignatureListHead);
/* Create one large blob of free memory */
MdEntry = KiRosGetMdFromArray();
MdEntry->MemoryType = LoaderFree;
MdEntry->BasePage = 0;
MdEntry->PageCount = MmFreeLdrMemHigher / 4;
InsertTailList(&LoaderBlock->MemoryDescriptorListHead, &MdEntry->ListEntry);
/*
* FIXME: Instead of just "inserting" MDs into the list,
* we need to make then be "consumed" from the Free Descriptor.
* This will happen soon (and also ensure a sorted list).
*/
/* Loop the BIOS Memory Map */
for (j = 0; j < KeMemoryMapRangeCount; j++)
{
/* Check if this is a reserved entry */
if (KeMemoryMap[j].Type == 2)
{
/* It is, build an entry for it */
MdEntry = KiRosGetMdFromArray();
MdEntry->MemoryType = LoaderSpecialMemory;
MdEntry->BasePage = KeMemoryMap[j].BaseAddrLow >> PAGE_SHIFT;
MdEntry->PageCount = (KeMemoryMap[j].LengthLow + PAGE_SIZE - 1) >> PAGE_SHIFT;
InsertTailList(&LoaderBlock->MemoryDescriptorListHead,
&MdEntry->ListEntry);
}
}
/* Page 0 is reserved: build an entry for it */
MdEntry = KiRosGetMdFromArray();
MdEntry->MemoryType = LoaderFirmwarePermanent;
MdEntry->BasePage = 0;
MdEntry->PageCount = 1;
InsertTailList(&LoaderBlock->MemoryDescriptorListHead, &MdEntry->ListEntry);
/* Build an entry for the KPCR (which we put in page 1) */
MdEntry = KiRosGetMdFromArray();
MdEntry->MemoryType = LoaderMemoryData;
MdEntry->BasePage = 1;
MdEntry->PageCount = 1;
InsertTailList(&LoaderBlock->MemoryDescriptorListHead, &MdEntry->ListEntry);
/* Build an entry for the PDE */
MdEntry = KiRosGetMdFromArray();
MdEntry->MemoryType = LoaderMemoryData;
MdEntry->BasePage = (ULONG_PTR)MmGetPageDirectory() >> PAGE_SHIFT;
MdEntry->PageCount = (MmFreeLdrPageDirectoryEnd -
(ULONG_PTR)MmGetPageDirectory()) / PAGE_SIZE;
InsertTailList(&LoaderBlock->MemoryDescriptorListHead, &MdEntry->ListEntry);
/* Mark Video ROM as reserved */
MdEntry = KiRosGetMdFromArray();
MdEntry->MemoryType = LoaderFirmwarePermanent;
MdEntry->BasePage = 0xA0000 >> PAGE_SHIFT;
MdEntry->PageCount = (0xE8000 - 0xA0000) / PAGE_SIZE;
InsertTailList(&LoaderBlock->MemoryDescriptorListHead, &MdEntry->ListEntry);
/* Loop boot driver list */
for (i = 0; i < RosLoaderBlock->ModsCount; i++)
{
@ -106,9 +180,9 @@ KiRosFrldrLpbToNtLpb(IN PROS_LOADER_PARAMETER_BLOCK RosLoaderBlock,
LoaderBlock->NlsData->AnsiCodePageData = ModStart;
/* Create an MD for it */
MdEntry = &BldrMemoryDescriptors[i];
MdEntry = KiRosGetMdFromArray();
MdEntry->MemoryType = LoaderNlsData;
MdEntry->BasePage = (ULONG_PTR)ModStart >> PAGE_SHIFT;
MdEntry->BasePage = ((ULONG_PTR)ModStart &~ KSEG0_BASE) >> PAGE_SHIFT;
MdEntry->PageCount = (ModSize + PAGE_SIZE - 1)>> PAGE_SHIFT;
InsertTailList(&LoaderBlock->MemoryDescriptorListHead,
&MdEntry->ListEntry);
@ -121,9 +195,9 @@ KiRosFrldrLpbToNtLpb(IN PROS_LOADER_PARAMETER_BLOCK RosLoaderBlock,
LoaderBlock->NlsData->OemCodePageData = ModStart;
/* Create an MD for it */
MdEntry = &BldrMemoryDescriptors[i];
MdEntry = KiRosGetMdFromArray();
MdEntry->MemoryType = LoaderNlsData;
MdEntry->BasePage = (ULONG_PTR)ModStart >> PAGE_SHIFT;
MdEntry->BasePage = ((ULONG_PTR)ModStart &~ KSEG0_BASE) >> PAGE_SHIFT;
MdEntry->PageCount = (ModSize + PAGE_SIZE - 1) >> PAGE_SHIFT;
InsertTailList(&LoaderBlock->MemoryDescriptorListHead,
&MdEntry->ListEntry);
@ -136,9 +210,9 @@ KiRosFrldrLpbToNtLpb(IN PROS_LOADER_PARAMETER_BLOCK RosLoaderBlock,
LoaderBlock->NlsData->UnicodeCodePageData = ModStart;
/* Create an MD for it */
MdEntry = &BldrMemoryDescriptors[i];
MdEntry = KiRosGetMdFromArray();
MdEntry->MemoryType = LoaderNlsData;
MdEntry->BasePage = (ULONG_PTR)ModStart >> PAGE_SHIFT;
MdEntry->BasePage = ((ULONG_PTR)ModStart &~ KSEG0_BASE) >> PAGE_SHIFT;
MdEntry->PageCount = (ModSize + PAGE_SIZE - 1) >> PAGE_SHIFT;
InsertTailList(&LoaderBlock->MemoryDescriptorListHead,
&MdEntry->ListEntry);
@ -158,9 +232,9 @@ KiRosFrldrLpbToNtLpb(IN PROS_LOADER_PARAMETER_BLOCK RosLoaderBlock,
LoaderBlock->SetupLdrBlock = NULL;
/* Create an MD for it */
MdEntry = &BldrMemoryDescriptors[i];
MdEntry = KiRosGetMdFromArray();
MdEntry->MemoryType = LoaderRegistryData;
MdEntry->BasePage = (ULONG_PTR)ModStart >> PAGE_SHIFT;
MdEntry->BasePage = ((ULONG_PTR)ModStart &~ KSEG0_BASE) >> PAGE_SHIFT;
MdEntry->PageCount = (ModSize + PAGE_SIZE - 1) >> PAGE_SHIFT;
InsertTailList(&LoaderBlock->MemoryDescriptorListHead,
&MdEntry->ListEntry);
@ -173,9 +247,9 @@ KiRosFrldrLpbToNtLpb(IN PROS_LOADER_PARAMETER_BLOCK RosLoaderBlock,
{
/* Create an MD for it */
ModStart = RVA(ModStart, KSEG0_BASE);
MdEntry = &BldrMemoryDescriptors[i];
MdEntry = KiRosGetMdFromArray();
MdEntry->MemoryType = LoaderRegistryData;
MdEntry->BasePage = (ULONG_PTR)ModStart >> PAGE_SHIFT;
MdEntry->BasePage = ((ULONG_PTR)ModStart &~ KSEG0_BASE) >> PAGE_SHIFT;
MdEntry->PageCount = (ModSize + PAGE_SIZE - 1) >> PAGE_SHIFT;
InsertTailList(&LoaderBlock->MemoryDescriptorListHead,
&MdEntry->ListEntry);
@ -186,9 +260,9 @@ KiRosFrldrLpbToNtLpb(IN PROS_LOADER_PARAMETER_BLOCK RosLoaderBlock,
if (!(_stricmp(DriverName, "ntoskrnl.exe")))
{
/* Create an MD for it */
MdEntry = &BldrMemoryDescriptors[i];
MdEntry = KiRosGetMdFromArray();
MdEntry->MemoryType = LoaderSystemCode;
MdEntry->BasePage = (ULONG_PTR)ModStart >> PAGE_SHIFT;
MdEntry->BasePage = ((ULONG_PTR)ModStart &~ KSEG0_BASE) >> PAGE_SHIFT;
MdEntry->PageCount = (ModSize + PAGE_SIZE - 1) >> PAGE_SHIFT;
InsertTailList(&LoaderBlock->MemoryDescriptorListHead,
&MdEntry->ListEntry);
@ -196,9 +270,9 @@ KiRosFrldrLpbToNtLpb(IN PROS_LOADER_PARAMETER_BLOCK RosLoaderBlock,
else if (!(_stricmp(DriverName, "hal.dll")))
{
/* Create an MD for the HAL */
MdEntry = &BldrMemoryDescriptors[i];
MdEntry = KiRosGetMdFromArray();
MdEntry->MemoryType = LoaderHalCode;
MdEntry->BasePage = (ULONG_PTR)ModStart >> PAGE_SHIFT;
MdEntry->BasePage = ((ULONG_PTR)ModStart &~ KSEG0_BASE) >> PAGE_SHIFT;
MdEntry->PageCount = (ModSize + PAGE_SIZE - 1) >> PAGE_SHIFT;
InsertTailList(&LoaderBlock->MemoryDescriptorListHead,
&MdEntry->ListEntry);
@ -206,9 +280,9 @@ KiRosFrldrLpbToNtLpb(IN PROS_LOADER_PARAMETER_BLOCK RosLoaderBlock,
else
{
/* Create an MD for any driver */
MdEntry = &BldrMemoryDescriptors[i];
MdEntry = KiRosGetMdFromArray();
MdEntry->MemoryType = LoaderBootDriver;
MdEntry->BasePage = (ULONG_PTR)ModStart >> PAGE_SHIFT;
MdEntry->BasePage = ((ULONG_PTR)ModStart &~ KSEG0_BASE) >> PAGE_SHIFT;
MdEntry->PageCount = (ModSize + PAGE_SIZE - 1) >> PAGE_SHIFT;
InsertTailList(&LoaderBlock->MemoryDescriptorListHead,
&MdEntry->ListEntry);
@ -356,6 +430,7 @@ KiRosPrepareForSystemStartup(IN ULONG Dummy,
IN PROS_LOADER_PARAMETER_BLOCK LoaderBlock)
{
PLOADER_PARAMETER_BLOCK NtLoaderBlock;
ULONG size, i;
#if defined(_M_IX86)
PKTSS Tss;
PKGDTENTRY TssEntry;
@ -387,6 +462,39 @@ KiRosPrepareForSystemStartup(IN ULONG Dummy,
KSEG0_BASE;
MmFreeLdrLastKrnlPhysAddr = MmFreeLdrLastKernelAddress - KSEG0_BASE;
KeMemoryMapRangeCount = 0;
if (LoaderBlock->Flags & MB_FLAGS_MMAP_INFO)
{
/* We have a memory map from the nice BIOS */
size = *((PULONG)(LoaderBlock->MmapAddr - sizeof(ULONG)));
i = 0;
/* Map it until we run out of size */
while (i < LoaderBlock->MmapLength)
{
/* Copy into the Kernel Memory Map */
memcpy (&KeMemoryMap[KeMemoryMapRangeCount],
(PVOID)(LoaderBlock->MmapAddr + i),
sizeof(ADDRESS_RANGE));
/* Increase Memory Map Count */
KeMemoryMapRangeCount++;
/* Increase Size */
i += size;
}
/* Save data */
LoaderBlock->MmapLength = KeMemoryMapRangeCount * sizeof(ADDRESS_RANGE);
LoaderBlock->MmapAddr = (ULONG)KeMemoryMap;
}
else
{
/* Nothing from BIOS */
LoaderBlock->MmapLength = 0;
LoaderBlock->MmapAddr = (ULONG)KeMemoryMap;
}
#if defined(_M_IX86)
/* Set up the VDM Data */
NtEarlyInitVdm();

View file

@ -18,6 +18,10 @@
KSPIN_LOCK KiFreezeExecutionLock;
KSPIN_LOCK Ki486CompatibilityLock;
/* BIOS Memory Map. Not NTLDR-compliant yet */
extern ULONG KeMemoryMapRangeCount;
extern ADDRESS_RANGE KeMemoryMap[64];
/* FUNCTIONS *****************************************************************/
VOID
@ -536,8 +540,8 @@ KiInitializeKernel(IN PKPROCESS InitProcess,
MmInit1(MmFreeLdrFirstKrnlPhysAddr,
MmFreeLdrLastKrnlPhysAddr,
MmFreeLdrLastKernelAddress,
NULL,
0,
KeMemoryMap,
KeMemoryMapRangeCount,
4096);
/* Set basic CPU Features that user mode can read */

View file

@ -301,6 +301,34 @@ MmInitVirtualMemory(ULONG_PTR LastKernelAddress,
MmInitializeMemoryConsumer(MC_USER, MmTrimUserMemory);
}
PCHAR
MemType[] = {
"ExceptionBlock ", // ?
"SystemBlock ", // ?
"Free ",
"Bad ", // used
"LoadedProgram ", // == Free
"FirmwareTemporary ", // == Free
"FirmwarePermanent ", // == Bad
"OsloaderHeap ", // used
"OsloaderStack ", // == Free
"SystemCode ",
"HalCode ",
"BootDriver ", // not used
"ConsoleInDriver ", // ?
"ConsoleOutDriver ", // ?
"StartupDpcStack ", // ?
"StartupKernelStack", // ?
"StartupPanicStack ", // ?
"StartupPcrPage ", // ?
"StartupPdrPage ", // ?
"RegistryData ", // used
"MemoryData ", // not used
"NlsData ", // used
"SpecialMemory ", // == Bad
"BBTMemory " // == Bad
};
VOID
INIT_FUNCTION
NTAPI
@ -324,6 +352,25 @@ MmInit1(ULONG_PTR FirstKrnlPhysAddr,
LastKrnlPhysAddr,
LastKernelAddress);
/* Dump memory descriptors */
{
PLIST_ENTRY NextEntry;
PMEMORY_ALLOCATION_DESCRIPTOR Md;
ULONG TotalPages = 0;
DPRINT1("Base\t\tLength\t\tType\n");
for (NextEntry = KeLoaderBlock->MemoryDescriptorListHead.Flink;
NextEntry != &KeLoaderBlock->MemoryDescriptorListHead;
NextEntry = NextEntry->Flink)
{
Md = CONTAINING_RECORD(NextEntry, MEMORY_ALLOCATION_DESCRIPTOR, ListEntry);
DPRINT1("%08lX\t%08lX\t%s\n", Md->BasePage, Md->PageCount, MemType[Md->MemoryType]);
TotalPages += Md->PageCount;
}
DPRINT1("Total: %08lX (%d MB)\n", TotalPages, (TotalPages * PAGE_SIZE) / 1024 / 1024);
}
/* Set the page directory */
PsGetCurrentProcess()->Pcb.DirectoryTableBase.LowPart = (ULONG)MmGetPageDirectory();