mirror of
https://github.com/reactos/reactos.git
synced 2024-08-13 06:37:06 +00:00
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. svn path=/trunk/; revision=34292
This commit is contained in:
parent
97f94beafc
commit
b33ec42e10
|
@ -111,6 +111,14 @@ FrLdrMapImage(
|
|||
IN ULONG ImageType
|
||||
);
|
||||
|
||||
PVOID
|
||||
NTAPI
|
||||
FrLdrReadAndMapImage(
|
||||
IN FILE *Image,
|
||||
IN PCHAR ShortName,
|
||||
IN ULONG ImageType
|
||||
);
|
||||
|
||||
PVOID
|
||||
NTAPI
|
||||
FrLdrLoadImage(
|
||||
|
|
|
@ -434,6 +434,174 @@ LdrPEFixupImports(IN PVOID DllBase,
|
|||
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
|
||||
NTAPI
|
||||
FrLdrReMapImage(IN PVOID Base,
|
||||
|
@ -519,6 +687,12 @@ FrLdrMapImage(IN FILE *Image,
|
|||
|
||||
/* 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))
|
||||
|
|
|
@ -120,7 +120,7 @@ FrLdrLoadDriver(PCHAR szFileName,
|
|||
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 @@ FrLdrLoadImage(IN PCHAR szFileName,
|
|||
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);
|
||||
|
|
|
@ -82,7 +82,7 @@ static FrLdrLoadKernel(IN PCHAR szFileName,
|
|||
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);
|
||||
|
|
Loading…
Reference in a new issue