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/includ... ============================================================================== --- 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/reacto... ============================================================================== --- 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/reacto... ============================================================================== --- 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/reacto... ============================================================================== --- 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);