[ros-diffs] [fireball] 28537: - 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.

fireball at svn.reactos.org fireball at svn.reactos.org
Sat Aug 25 11:38:13 CEST 2007


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/reactos/reactos.c?rev=28537&r1=28536&r2=28537&view=diff
==============================================================================
--- 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=28537&r1=28536&r2=28537&view=diff
==============================================================================
--- 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?rev=28537&r1=28536&r2=28537&view=diff
==============================================================================
--- 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=28537&r1=28536&r2=28537&view=diff
==============================================================================
--- 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();
 




More information about the Ros-diffs mailing list