[ros-diffs] [fireball] 34292: Dmitry Gorbachev: - FreeLoader first reads entire ntoskrnl.exe (about 20M) into memory, then copies it to other address. Now, freeldr reads it straight to the place, not allocating extra memory for buffer. - Aleksey: This changes should be eventually adopted and merged into winldr's peloader.c. See issue #3447 for more details.

fireball at svn.reactos.org fireball at svn.reactos.org
Fri Jul 4 12:36:03 CEST 2008


Author: fireball
Date: Fri Jul  4 05:36:03 2008
New Revision: 34292

URL: http://svn.reactos.org/svn/reactos?rev=34292&view=rev
Log:
Dmitry Gorbachev:
- FreeLoader first reads entire ntoskrnl.exe (about 20M) into memory, then copies it to other address. Now, freeldr reads it straight to the place, not allocating extra memory for buffer.
- Aleksey: This changes should be eventually adopted and merged into winldr's peloader.c.
See issue #3447 for more details.

Modified:
    trunk/reactos/boot/freeldr/freeldr/include/reactos.h
    trunk/reactos/boot/freeldr/freeldr/reactos/imageldr.c
    trunk/reactos/boot/freeldr/freeldr/reactos/reactos.c
    trunk/reactos/boot/freeldr/freeldr/reactos/setupldr.c

Modified: trunk/reactos/boot/freeldr/freeldr/include/reactos.h
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/boot/freeldr/freeldr/include/reactos.h?rev=34292&r1=34291&r2=34292&view=diff
==============================================================================
--- trunk/reactos/boot/freeldr/freeldr/include/reactos.h [iso-8859-1] (original)
+++ trunk/reactos/boot/freeldr/freeldr/include/reactos.h [iso-8859-1] Fri Jul  4 05:36:03 2008
@@ -113,6 +113,14 @@
 
 PVOID
 NTAPI
+FrLdrReadAndMapImage(
+    IN FILE *Image,
+    IN PCHAR ShortName,
+    IN ULONG ImageType
+);
+
+PVOID
+NTAPI
 FrLdrLoadImage(
     IN PCHAR szFileName,
     IN INT nPos,

Modified: trunk/reactos/boot/freeldr/freeldr/reactos/imageldr.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/boot/freeldr/freeldr/reactos/imageldr.c?rev=34292&r1=34291&r2=34292&view=diff
==============================================================================
--- trunk/reactos/boot/freeldr/freeldr/reactos/imageldr.c [iso-8859-1] (original)
+++ trunk/reactos/boot/freeldr/freeldr/reactos/imageldr.c [iso-8859-1] Fri Jul  4 05:36:03 2008
@@ -432,6 +432,174 @@
     }
     
     return STATUS_SUCCESS;
+}
+
+PVOID
+NTAPI
+FrLdrReadAndMapImage(IN FILE *Image,
+                     IN PCHAR Name,
+                     IN ULONG ImageType)
+{
+    PVOID ImageBase, LoadBase, ReadBuffer;
+    ULONG ImageId = LoaderBlock.ModsCount;
+    ULONG i, Size, ImageSize, SizeOfHeaders;
+    PIMAGE_NT_HEADERS NtHeader;
+    PIMAGE_SECTION_HEADER Section;
+    NTSTATUS Status = STATUS_SUCCESS;
+
+    /* Try to see, maybe it's loaded already */
+    if (LdrGetModuleObject(Name) != NULL)
+    {
+        /* It's loaded, return NULL. It would be wise to return
+         correct LoadBase, but it seems to be ignored almost everywhere */
+        return NULL;
+    }
+
+    /* Set the virtual (image) and physical (load) addresses */
+    LoadBase = (PVOID)NextModuleBase;
+    ImageBase = RVA(LoadBase, KSEG0_BASE);
+
+    /* Allocate a temporary buffer for the read */
+    ReadBuffer = MmHeapAlloc(MM_PAGE_SIZE);
+    if (!ReadBuffer)
+    {
+        /* Fail */
+        DbgPrint("Failed to allocate a temporary buffer for the read\n");
+        return NULL;
+    }
+
+    /* Set the file pointer to zero */
+    FsSetFilePointer(Image, 0);
+
+    /* Load first page of the file image */
+    if (!FsReadFile(Image, MM_PAGE_SIZE, NULL, ReadBuffer))
+    {
+        /* Fail */
+        DbgPrint("Failed to read image: %s\n", Name);
+        return NULL;
+    }
+
+    /* Get image headers */
+    NtHeader = RtlImageNtHeader(ReadBuffer);
+
+    /* Allocate memory for the driver */
+    ImageSize = NtHeader->OptionalHeader.SizeOfImage;
+    LoadBase = MmAllocateMemoryAtAddress(ImageSize, LoadBase, LoaderSystemCode);
+    ASSERT(LoadBase);
+
+    /* Copy headers over */
+    SizeOfHeaders = NtHeader->OptionalHeader.SizeOfHeaders;
+    if (SizeOfHeaders < MM_PAGE_SIZE)
+    {
+        RtlMoveMemory(LoadBase, ReadBuffer, SizeOfHeaders);
+    }
+    else
+    {
+        RtlMoveMemory(LoadBase, ReadBuffer, MM_PAGE_SIZE);
+        if (!FsReadFile(Image, SizeOfHeaders - MM_PAGE_SIZE, NULL,
+                        (PVOID)((ULONG_PTR)LoadBase + MM_PAGE_SIZE)))
+        {
+            DbgPrint("Failed to read image: %s\n", Name);
+            return NULL;
+        }
+    }
+
+    /* Free the temporary buffer */
+    MmHeapFree(ReadBuffer);
+
+    /* Get the first section */
+    NtHeader = RtlImageNtHeader(LoadBase);
+    Section = IMAGE_FIRST_SECTION(NtHeader);
+
+    /*  Read image sections into virtual section  */
+    for (i = 0; i < NtHeader->FileHeader.NumberOfSections; i++)
+    {
+        /* Get the size of this section and check if it's valid */
+        Size = Section[i].VirtualAddress + Section[i].Misc.VirtualSize;
+        if (Size <= ImageSize)
+        {
+            if (Section[i].SizeOfRawData)
+            {
+                /* Copy the data from the disk to the image */
+                FsSetFilePointer(Image, Section[i].PointerToRawData);
+                if (!FsReadFile(Image,
+                                Section[i].Misc.VirtualSize >
+                                Section[i].SizeOfRawData ?
+                                Section[i].SizeOfRawData :
+                                Section[i].Misc.VirtualSize,
+                                NULL,
+                                (PVOID)((ULONG_PTR)LoadBase +
+                                        Section[i].VirtualAddress)))
+                {
+                    DbgPrint("Failed to read image: %s\n", Name);
+                    return NULL;
+                }
+            }
+            else
+            {
+                /* Clear the BSS area */
+                RtlZeroMemory((PVOID)((ULONG_PTR)LoadBase +
+                                      Section[i].VirtualAddress),
+                              Section[i].Misc.VirtualSize);
+            }
+        }
+    }
+
+    /* Calculate Difference between Real Base and Compiled Base*/
+    Status = LdrRelocateImageWithBias(LoadBase,
+                                      (ULONG_PTR)ImageBase -
+                                      (ULONG_PTR)LoadBase,
+                                      "FreeLdr",
+                                      STATUS_SUCCESS,
+                                      STATUS_UNSUCCESSFUL,
+                                      STATUS_UNSUCCESSFUL);
+    if (!NT_SUCCESS(Status))
+    {
+        /* Fail */
+        DbgPrint("Failed to relocate image: %s\n", Name);
+        return NULL;
+    }
+
+    /* Fill out Module Data Structure */
+    reactos_modules[ImageId].ModStart = (ULONG_PTR)ImageBase;
+    reactos_modules[ImageId].ModEnd = (ULONG_PTR)ImageBase + ImageSize;
+    strcpy(reactos_module_strings[ImageId], Name);
+    reactos_modules[ImageId].String = (ULONG_PTR)reactos_module_strings[ImageId];
+    LoaderBlock.ModsCount++;
+
+    /* Detect kernel or HAL */
+    if (!_stricmp(Name, "ntoskrnl.exe"))
+    {
+        KernelData = (PVOID)NextModuleBase;
+        KernelSize = ImageSize;
+    }
+    else if (!_stricmp(Name, "hal.dll"))
+    {
+        HalData = (PVOID)NextModuleBase;
+        HalSize = ImageSize;
+    }
+    else
+    {
+        DriverName[Drivers] = reactos_module_strings[ImageId];
+        DriverData[Drivers] = (PVOID)NextModuleBase;
+        DriverSize[Drivers] = ImageSize;
+        Drivers++;
+    }
+
+    /* Increase the next Load Base */
+    NextModuleBase = ROUND_UP(NextModuleBase + ImageSize, PAGE_SIZE);
+
+    /* Perform import fixups */
+    if (!NT_SUCCESS(LdrPEFixupImports(LoadBase, Name)))
+    {
+        /* Fixup failed, just don't include it in the list */
+        // NextModuleBase = OldNextModuleBase;
+        LoaderBlock.ModsCount = ImageId;
+        return NULL;
+    }
+
+    /* Return the final mapped address */
+    return LoadBase;
 }
 
 ULONG
@@ -519,6 +687,12 @@
     
     /* Allocate a temporary buffer for the read */
     ReadBuffer = MmHeapAlloc(ImageSize);
+    if (!ReadBuffer)
+    {
+        /* Fail */
+        DbgPrint("Failed to allocate a temporary buffer for the read\n");
+        return NULL;
+    }
 
     /* Load the file image */
     if (!FsReadFile(Image, ImageSize, NULL, ReadBuffer))

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=34292&r1=34291&r2=34292&view=diff
==============================================================================
--- trunk/reactos/boot/freeldr/freeldr/reactos/reactos.c [iso-8859-1] (original)
+++ trunk/reactos/boot/freeldr/freeldr/reactos/reactos.c [iso-8859-1] Fri Jul  4 05:36:03 2008
@@ -120,7 +120,7 @@
     UiDrawStatusText(value);
 
     /* Load the driver */
-    FrLdrMapImage(FilePointer, szFileName, 0);
+    FrLdrReadAndMapImage(FilePointer, szFileName, 0);
 
     /* Update status and return */
     UiDrawProgressBarCenter(nPos, 100, szLoadingMsg);
@@ -182,7 +182,7 @@
     UiDrawStatusText(szBuffer);
 
     /* Do the actual loading */
-    LoadBase = FrLdrMapImage(FilePointer, szShortName, ImageType);
+    LoadBase = FrLdrReadAndMapImage(FilePointer, szShortName, ImageType);
 
     /* Update Processbar and return success */
     if (!FrLdrBootType) UiDrawProgressBarCenter(nPos, 100, szLoadingMsg);

Modified: trunk/reactos/boot/freeldr/freeldr/reactos/setupldr.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/boot/freeldr/freeldr/reactos/setupldr.c?rev=34292&r1=34291&r2=34292&view=diff
==============================================================================
--- trunk/reactos/boot/freeldr/freeldr/reactos/setupldr.c [iso-8859-1] (original)
+++ trunk/reactos/boot/freeldr/freeldr/reactos/setupldr.c [iso-8859-1] Fri Jul  4 05:36:03 2008
@@ -82,7 +82,7 @@
     UiDrawStatusText(szBuffer);
 
     /* Do the actual loading */
-    LoadBase = FrLdrMapImage(FilePointer, szShortName, 1);
+    LoadBase = FrLdrReadAndMapImage(FilePointer, szShortName, 1);
 
     /* Get the NT header, kernel base and kernel entry */
     NtHeader = RtlImageNtHeader(LoadBase);



More information about the Ros-diffs mailing list