Author: fireball
Date: Sat Aug 25 13:38:13 2007
New Revision: 28537
URL:
http://svn.reactos.org/svn/reactos?rev=28537&view=rev
Log:
- 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.
Modified:
trunk/reactos/boot/freeldr/freeldr/reactos/reactos.c
trunk/reactos/ntoskrnl/ke/freeldr.c
trunk/reactos/ntoskrnl/ke/i386/kiinit.c
trunk/reactos/ntoskrnl/mm/mminit.c
Modified: trunk/reactos/boot/freeldr/freeldr/reactos/reactos.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/boot/freeldr/freeldr/react…
==============================================================================
--- trunk/reactos/boot/freeldr/freeldr/reactos/reactos.c (original)
+++ trunk/reactos/boot/freeldr/freeldr/reactos/reactos.c Sat Aug 25 13:38:13 2007
@@ -599,7 +599,7 @@
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++)
Modified: trunk/reactos/ntoskrnl/ke/freeldr.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/ke/freeldr.c?rev=…
==============================================================================
--- trunk/reactos/ntoskrnl/ke/freeldr.c (original)
+++ trunk/reactos/ntoskrnl/ke/freeldr.c Sat Aug 25 13:38:13 2007
@@ -23,6 +23,12 @@
/* 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
@@ -44,6 +50,15 @@
// 0x1443C
/* 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
@@ -69,6 +84,7 @@
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;
@@ -88,6 +104,64 @@
InitializeListHead(&LoaderBlock->MemoryDescriptorListHead);
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 @@
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 @@
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 @@
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 @@
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 @@
{
/* 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 @@
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 @@
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 @@
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 @@
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 @@
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();
Modified: trunk/reactos/ntoskrnl/ke/i386/kiinit.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/ke/i386/kiinit.c?…
==============================================================================
--- trunk/reactos/ntoskrnl/ke/i386/kiinit.c (original)
+++ trunk/reactos/ntoskrnl/ke/i386/kiinit.c Sat Aug 25 13:38:13 2007
@@ -17,6 +17,10 @@
/* Spinlocks used only on X86 */
KSPIN_LOCK KiFreezeExecutionLock;
KSPIN_LOCK Ki486CompatibilityLock;
+
+/* BIOS Memory Map. Not NTLDR-compliant yet */
+extern ULONG KeMemoryMapRangeCount;
+extern ADDRESS_RANGE KeMemoryMap[64];
/* FUNCTIONS *****************************************************************/
@@ -536,8 +540,8 @@
MmInit1(MmFreeLdrFirstKrnlPhysAddr,
MmFreeLdrLastKrnlPhysAddr,
MmFreeLdrLastKernelAddress,
- NULL,
- 0,
+ KeMemoryMap,
+ KeMemoryMapRangeCount,
4096);
/* Set basic CPU Features that user mode can read */
Modified: trunk/reactos/ntoskrnl/mm/mminit.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/mm/mminit.c?rev=2…
==============================================================================
--- trunk/reactos/ntoskrnl/mm/mminit.c (original)
+++ trunk/reactos/ntoskrnl/mm/mminit.c Sat Aug 25 13:38:13 2007
@@ -301,6 +301,34 @@
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 @@
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();