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/i... ============================================================================== --- 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=25... ============================================================================== --- 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,