Author: ion
Date: Fri Feb 23 22:48:25 2007
New Revision: 25894
URL:
http://svn.reactos.org/svn/reactos?rev=25894&view=rev
Log:
- Update FreeLDR PE Loading to actually use its Mm routines to allocate a buffer to read
an image file into, then to allocate the actual load base and use the same code as in
sysldr.c right now to PE-load the image into memory, then free the original read buffer.
Not yet enabled for drivers!
- This means that:
- 1) FreeLDR now keeps memory accounting information for the image files it loads,
instead of us randomly writing to memory.
- 2) We now skip sections marked as NO_LOAD. The kernel already re-mapped drivers doing
this, but it didn't remap the kernel/hal, plus we still had to map the drivers once in
FreeLDR, so we're saving a meg+ of kernel memory.
Modified:
trunk/reactos/boot/freeldr/freeldr/arch/i386/loader.c
trunk/reactos/ntoskrnl/io/iomgr/driver.c
trunk/reactos/ntoskrnl/mm/sysldr.c
Modified: trunk/reactos/boot/freeldr/freeldr/arch/i386/loader.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/boot/freeldr/freeldr/arch/…
==============================================================================
--- trunk/reactos/boot/freeldr/freeldr/arch/i386/loader.c (original)
+++ trunk/reactos/boot/freeldr/freeldr/arch/i386/loader.c Fri Feb 23 22:48:25 2007
@@ -598,46 +598,64 @@
return STATUS_SUCCESS;
}
-VOID
-NTAPI
-FrLdrReMapImage(IN PIMAGE_NT_HEADERS NtHeader,
- IN PVOID Base)
-{
+ULONG
+NTAPI
+FrLdrReMapImage(IN PVOID Base,
+ IN PVOID LoadBase)
+{
+ PIMAGE_NT_HEADERS NtHeader;
PIMAGE_SECTION_HEADER Section;
- ULONG SectionCount, SectionSize;
- PVOID SourceSection, TargetSection;
- INT i;
-
- /* Load the first section */
+ ULONG i, Size, DriverSize = 0;
+
+ /* Get the first section */
+ NtHeader = RtlImageNtHeader(Base);
Section = IMAGE_FIRST_SECTION(NtHeader);
- SectionCount = NtHeader->FileHeader.NumberOfSections - 1;
-
- /* Now go to the last section */
- Section += SectionCount;
-
- /* Walk each section backwards */
- for (i = SectionCount; i >= 0; i--, Section--)
- {
- /* Get the disk location and the memory location, and the size */
- SourceSection = RVA(Base, Section->PointerToRawData);
- TargetSection = RVA(Base, Section->VirtualAddress);
- SectionSize = Section->SizeOfRawData;
-
- /* If the section is already mapped correctly, go to the next */
- if (SourceSection == TargetSection) continue;
-
- /* Load it into memory */
- RtlMoveMemory(TargetSection, SourceSection, SectionSize);
-
- /* Check for uninitialized data */
- if (Section->SizeOfRawData < Section->Misc.VirtualSize)
- {
- /* Zero it out */
- RtlZeroMemory(RVA(Base, Section->VirtualAddress +
- Section->SizeOfRawData),
- Section->Misc.VirtualSize - Section->SizeOfRawData);
- }
- }
+
+ /* Determine the size of the module */
+ for (i = 0; i < NtHeader->FileHeader.NumberOfSections; i++)
+ {
+ /* Skip this section if we're not supposed to load it */
+ if (!(Section[i].Characteristics & IMAGE_SCN_TYPE_NOLOAD))
+ {
+ /* Add the size of this section into the total size */
+ Size = Section[i].VirtualAddress + Section[i].Misc.VirtualSize;
+ DriverSize = max(DriverSize, Size);
+ }
+ }
+
+ /* Round up the driver size to section alignment */
+ DriverSize = ROUND_UP(DriverSize, NtHeader->OptionalHeader.SectionAlignment);
+
+ /* Allocate memory for the driver */
+ LoadBase = MmAllocateMemoryAtAddress(DriverSize, LoadBase);
+ ASSERT(LoadBase);
+
+ /* Copy headers over */
+ RtlMoveMemory(LoadBase,
+ Base,
+ NtHeader->OptionalHeader.SizeOfHeaders);
+
+ /* Copy 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 and on-disk */
+ Size = Section[i].VirtualAddress + Section[i].Misc.VirtualSize;
+ if ((Size <= DriverSize) && (Section[i].SizeOfRawData))
+ {
+ /* Copy the data from the disk to the image */
+ RtlCopyMemory((PVOID)((ULONG_PTR)LoadBase +
+ Section[i].VirtualAddress),
+ (PVOID)((ULONG_PTR)Base +
+ Section[i].PointerToRawData),
+ Section[i].Misc.VirtualSize >
+ Section[i].SizeOfRawData ?
+ Section[i].SizeOfRawData :
+ Section[i].Misc.VirtualSize);
+ }
+ }
+
+ /* Return the size of the mapped driver */
+ return DriverSize;
}
BOOLEAN
@@ -646,32 +664,40 @@
IN PCHAR Name,
IN ULONG ImageType)
{
- PIMAGE_NT_HEADERS NtHeader;
- PVOID ImageBase, LoadBase;
+ PVOID ImageBase, LoadBase, ReadBuffer;
+ ULONG ImageId = LoaderBlock.ModsCount;
ULONG ImageSize;
- ULONG ImageId = LoaderBlock.ModsCount;
/* Set the virtual (image) and physical (load) addresses */
LoadBase = (PVOID)NextModuleBase;
ImageBase = RVA(LoadBase , -KERNEL_BASE_PHYS + KSEG0_BASE);
- /* Load the first 1024 bytes of the HAL image so we can read the PE header */
- if (!FsReadFile(Image, 1024, NULL, LoadBase)) return FALSE;
-
- /* Now read the MZ header to get the offset to the PE Header */
- NtHeader = RtlImageNtHeader(LoadBase);
-
/* Save the Image Size */
- ImageSize = NtHeader->OptionalHeader.SizeOfImage;
+ ImageSize = FsGetFileSize(Image);
/* Set the file pointer to zero */
FsSetFilePointer(Image, 0);
- /* Load the file image */
- FsReadFile(Image, ImageSize, NULL, LoadBase);
-
- /* Map it into virtual memory */
- if (ImageType != 2) FrLdrReMapImage(NtHeader, LoadBase);
+ if (ImageType != 2)
+ {
+ /* Allocate a temporary buffer for the read */
+ ReadBuffer = MmAllocateMemory(ImageSize);
+
+ /* Load the file image */
+ FsReadFile(Image, ImageSize, NULL, ReadBuffer);
+
+ /* Map it into virtual memory */
+ ImageSize = FrLdrReMapImage(ReadBuffer, LoadBase);
+
+ /* Free the temporary buffer */
+ MmFreeMemory(ReadBuffer);
+ }
+ else
+ {
+ /* Load the file image */
+ FsReadFile(Image, ImageSize, NULL, LoadBase);
+ ImageSize = RtlImageNtHeader(LoadBase)->OptionalHeader.SizeOfImage;
+ }
/* Calculate Difference between Real Base and Compiled Base*/
if (ImageType != 2) LdrRelocateImageWithBias(LoadBase,
@@ -698,6 +724,8 @@
/* Load HAL if this is the kernel */
if (ImageType == 1)
{
+ PIMAGE_NT_HEADERS NtHeader;
+ NtHeader = RtlImageNtHeader(LoadBase);
KernelBase = NtHeader->OptionalHeader.ImageBase;
KernelEntry = RaToPa(NtHeader->OptionalHeader.AddressOfEntryPoint);
FrLdrLoadImage("hal.dll", 10, FALSE);
Modified: trunk/reactos/ntoskrnl/io/iomgr/driver.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/io/iomgr/driver.c…
==============================================================================
--- trunk/reactos/ntoskrnl/io/iomgr/driver.c (original)
+++ trunk/reactos/ntoskrnl/io/iomgr/driver.c Fri Feb 23 22:48:25 2007
@@ -839,7 +839,9 @@
PWCHAR FileNameWithoutPath;
LPWSTR FileExtension;
PUNICODE_STRING ModuleName = &LdrEntry->BaseDllName;
+#if 1 // Disable for FreeLDR 2.5
PLDR_DATA_TABLE_ENTRY ModuleObject;
+#endif
/*
@@ -873,9 +875,11 @@
}
/*
- * Load the module. Remove for FreeLDR 2.5.
+ * Load the module.
*/
RtlCreateUnicodeString(&DeviceNode->ServiceName, FileNameWithoutPath);
+
+#if 1 // Remove for FreeLDR 2.5.
Status = LdrProcessDriverModule(LdrEntry, &DeviceNode->ServiceName,
&ModuleObject);
if (!NT_SUCCESS(Status))
{
@@ -883,6 +887,7 @@
CPRINT("Driver '%wZ' load failed, status (%x)\n", ModuleName,
Status);
return Status;
}
+#endif
/* Load symbols */
KDB_SYMBOLFILE_HOOK(ModuleName);
@@ -900,7 +905,7 @@
/*
* Initialize the driver
*/
- Status = IopInitializeDriverModule(DeviceNode, ModuleObject,
+ Status = IopInitializeDriverModule(DeviceNode, LdrEntry,
&DeviceNode->ServiceName, FALSE, &DriverObject);
if (!NT_SUCCESS(Status))
Modified: trunk/reactos/ntoskrnl/mm/sysldr.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/mm/sysldr.c?rev=2…
==============================================================================
--- trunk/reactos/ntoskrnl/mm/sysldr.c (original)
+++ trunk/reactos/ntoskrnl/mm/sysldr.c Fri Feb 23 22:48:25 2007
@@ -1063,8 +1063,10 @@
PIMAGE_DATA_DIRECTORY DataDirectory;
PVOID DllBase, NewImageAddress;
NTSTATUS Status;
+#if 1 // Disable for FreeLDR 2.5
ULONG DriverSize = 0, Size;
PIMAGE_SECTION_HEADER Section;
+#endif
/* Loop driver list */
for (NextEntry = LoaderBlock->LoadOrderListHead.Flink;
@@ -1157,7 +1159,7 @@
#if 0 // Enable for FreeLDR 2.5
/* Now copy the entire driver over */
- RtlCopyMemory(NewImageAddress, DllBase, DriverSize);
+ RtlCopyMemory(NewImageAddress, DllBase, LdrEntry->SizeOfImage);
#else
/* Copy headers over */
RtlCopyMemory(NewImageAddress,