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/inclu…
==============================================================================
--- 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/react…
==============================================================================
--- 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/react…
==============================================================================
--- 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/react…
==============================================================================
--- 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);