Author: ion
Date: Thu Jan 21 17:08:33 2016
New Revision: 70636
URL: http://svn.reactos.org/svn/reactos?rev=70636&view=rev
Log:
[BOOTLIB]: Fuck you binutils.
Modified:
trunk/reactos/boot/environ/CMakeLists.txt
trunk/reactos/boot/environ/lib/misc/image.c
Modified: trunk/reactos/boot/environ/CMakeLists.txt
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/boot/environ/CMakeLists.tx…
==============================================================================
--- trunk/reactos/boot/environ/CMakeLists.txt [iso-8859-1] (original)
+++ trunk/reactos/boot/environ/CMakeLists.txt [iso-8859-1] Thu Jan 21 17:08:33 2016
@@ -113,9 +113,9 @@
set_target_properties(rosload PROPERTIES SUFFIX ".efi")
if(MSVC)
- add_target_link_flags(rosload "/ignore:4078 /ignore:4254 /DRIVER /FIXED")
+ add_target_link_flags(rosload "/ignore:4078 /ignore:4254 /DRIVER")
else()
- add_target_link_flags(rosload "-Wl,--strip-all,--exclude-all-symbols")
+ add_target_link_flags(rosload "-Wl,--strip-all,--exclude-all-symbols,--dynamicbase,--pic-executable")
endif()
set_image_base(rosload 0x10000)
Modified: trunk/reactos/boot/environ/lib/misc/image.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/boot/environ/lib/misc/imag…
==============================================================================
--- trunk/reactos/boot/environ/lib/misc/image.c [iso-8859-1] (original)
+++ trunk/reactos/boot/environ/lib/misc/image.c [iso-8859-1] Thu Jan 21 17:08:33 2016
@@ -677,8 +677,10 @@
BOOLEAN First, ImageHashValid;
UCHAR LocalBuffer[1024];
UCHAR TrustedBootInformation[52];
+ ULONG WorkaroundForBinutils;
/* Initialize locals */
+ WorkaroundForBinutils = 0;
LocalFile = NULL;
ImageBuffer = NULL;
FileSize = 0;
@@ -881,6 +883,7 @@
/* Record our current position (right after the headers) */
EndOfHeaders = (ULONG_PTR)VirtualAddress + HeaderSize;
+ EfiPrintf(L"here\r\n");
/* Get the first section and iterate through each one */
Section = IMAGE_FIRST_SECTION(NtHeaders);
@@ -893,6 +896,7 @@
if ((VirtualSize < Section->VirtualAddress) ||
((PVOID)SectionStart < VirtualAddress))
{
+ EfiPrintf(L"fail 1\r\n");
Status = STATUS_INVALID_IMAGE_FORMAT;
goto Quickie;
}
@@ -940,6 +944,7 @@
&SectionEnd);
if (!NT_SUCCESS(Status))
{
+ EfiPrintf(L"fail 21\r\n");
Status = STATUS_INVALID_IMAGE_FORMAT;
goto Quickie;
}
@@ -957,6 +962,7 @@
&SectionEnd);
if (!NT_SUCCESS(Status))
{
+ EfiPrintf(L"fail 31\r\n");
Status = STATUS_INVALID_IMAGE_FORMAT;
goto Quickie;
}
@@ -974,6 +980,20 @@
/* Are we in the first iteration? */
if (!First)
{
+ /* FUCK YOU BINUTILS */
+ if ((*(PULONG)&Section->Name == 'ler.') && (RawSize < AlignSize))
+ {
+ /* Piece of shit won't build relocations when you tell it to,
+ * either by using --emit-relocs or --dynamicbase. People online
+ * have found out that by using -pie-executable you can get this
+ * to happen, but then it turns out that the .reloc section is
+ * incorrectly sized, and results in a corrupt PE. However, they
+ * still compute the checksum using the correct value. What idiots.
+ */
+ WorkaroundForBinutils = AlignSize - RawSize;
+ AlignSize -= WorkaroundForBinutils;
+ }
+
/* Yes, read the section data */
Status = ImgpReadAtFileOffset(LocalFile,
AlignSize,
@@ -994,6 +1014,7 @@
AlignSize,
BL_UTL_CHECKSUM_COMPLEMENT |
BL_UTL_CHECKSUM_USHORT_BUFFER);
+ AlignSize += WorkaroundForBinutils;
}
}
@@ -1075,7 +1096,7 @@
}
/* Finally, calculate the final checksum and compare it */
- FinalSum = FileSize + PartialSum;
+ FinalSum = FileSize + PartialSum + WorkaroundForBinutils;
if ((FinalSum != CheckSum) && (PartialSum == 0xFFFF))
{
/* It hit overflow, so set it to the file size */
@@ -1147,9 +1168,6 @@
{
*ImageSize = VirtualSize;
}
-
- EfiPrintf(L"MORE PE TODO: %lx\r\n", NtHeaders->OptionalHeader.AddressOfEntryPoint);
- EfiStall(100000000);
Quickie:
/* Check if we computed the image hash OK */
Author: ion
Date: Thu Jan 21 05:16:40 2016
New Revision: 70632
URL: http://svn.reactos.org/svn/reactos?rev=70632&view=rev
Log:
[BOOTLIB]: Implement checksum calculation for PE header sum.
[BOOTLIB]: Implement most of ImgpLoadPEImage. The checksum of the mapped image file matches the checksum in the flat PE file, meaning our load loop works as designed.
Next step are relocations and we'll be done.
Modified:
trunk/reactos/boot/environ/lib/misc/image.c
Modified: trunk/reactos/boot/environ/lib/misc/image.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/boot/environ/lib/misc/imag…
==============================================================================
--- trunk/reactos/boot/environ/lib/misc/image.c [iso-8859-1] (original)
+++ trunk/reactos/boot/environ/lib/misc/image.c [iso-8859-1] Thu Jan 21 05:16:40 2016
@@ -651,6 +651,54 @@
return BlImgUnallocateImageBuffer(ImageBase, ImageSize, ImageFlags);
}
+unsigned int BlUtlCheckSum(unsigned int PartialSum, PUCHAR Source, unsigned int Length, unsigned int Flags)
+{
+ unsigned int Type; // eax@1
+ int Type1; // eax@1
+ unsigned int AlignedLength; // ebx@3
+ unsigned int i; // ebx@21 MAPDST
+
+ Type = Flags & 3;
+ Type1 = Type - 1;
+ if (Type1)
+ {
+ if (Type1 == 1)
+ {
+ PartialSum = (unsigned __int16)PartialSum;
+ AlignedLength = Length & ~1;
+ if (Length & ~1)
+ {
+ i = 0;
+ do
+ {
+ PartialSum += *(unsigned __int16 *)&Source[i];
+ if (Flags & 0x10000)
+ PartialSum = (unsigned __int16)((PartialSum >> 16) + PartialSum);
+ i += 2;
+ } while (i < AlignedLength);
+ }
+
+ if (Length != AlignedLength)
+ {
+ PartialSum += (unsigned __int8)Source[AlignedLength];
+ if (Flags & 0x10000)
+ PartialSum = (unsigned __int16)((PartialSum >> 16) + PartialSum);
+ }
+ if (Flags & 0x40000)
+ return ~PartialSum;
+ PartialSum = (unsigned __int16)PartialSum;
+ }
+ }
+ else
+ {
+ EfiPrintf(L"checksum type not supported\r\n");
+ }
+
+ if (Flags & 0x40000)
+ return ~PartialSum;
+ return PartialSum;
+}
+
NTSTATUS
ImgpLoadPEImage (
_In_ PBL_IMG_FILE ImageFile,
@@ -670,11 +718,28 @@
ULONGLONG VirtualSize;
PHYSICAL_ADDRESS PhysicalAddress;
PIMAGE_NT_HEADERS NtHeaders;
+ USHORT SectionCount;
+ USHORT CheckSum, PartialSum;
+ PIMAGE_SECTION_HEADER Section;
+ ULONG_PTR EndOfHeaders, SectionStart;
+ ULONG i;
+ BOOLEAN First;
+ ULONG_PTR Slack, SectionEnd;
+ ULONG SectionSize, RawSize;
+ ULONG BytesRead, RemainingLength;
+ UCHAR LocalBuffer[1024];
+ USHORT FinalSum;
+ ULONG Offset;
+ ULONG AlignSize;
/* Initialize locals */
LocalFile = NULL;
ImageBuffer = NULL;
FileSize = 0;
+ First = FALSE;
+ VirtualAddress = NULL;
+ Offset = 0;
+ VirtualSize = 0;
/* Get the size of the image */
Status = ImgpGetFileSize(ImageFile, &FileSize);
@@ -846,6 +911,229 @@
goto Quickie;
}
+ First = FALSE;
+
+ /* Record how many sections we have */
+ SectionCount = NtHeaders->FileHeader.NumberOfSections;
+
+ /* Capture the current checksum and reset it */
+ CheckSum = NtHeaders->OptionalHeader.CheckSum;
+ NtHeaders->OptionalHeader.CheckSum = 0;
+
+ /* Calculate the checksum of the header, and restore the original one */
+ PartialSum = BlUtlCheckSum(0, VirtualAddress, HeaderSize, 0x10002);
+ NtHeaders->OptionalHeader.CheckSum = CheckSum;
+
+ /* Record our current position (right after the headers) */
+ EndOfHeaders = (ULONG_PTR)VirtualAddress + HeaderSize;
+
+ /* Get the first section and iterate through each one */
+ Section = IMAGE_FIRST_SECTION(NtHeaders);
+ for (i = 0; i < SectionCount; i++)
+ {
+ /* Compute where this section starts */
+ SectionStart = (ULONG_PTR)VirtualAddress + Section->VirtualAddress;
+
+ /* Make sure that the section fits within the image */
+ if ((VirtualSize < Section->VirtualAddress) ||
+ ((PVOID)SectionStart < VirtualAddress))
+ {
+ Status = STATUS_INVALID_IMAGE_FORMAT;
+ goto Quickie;
+ }
+
+ /* Check if there's slack space between header end and the section */
+ if (!(First) && (EndOfHeaders < SectionStart))
+ {
+ /* Zero it out */
+ Slack = SectionStart - EndOfHeaders;
+ RtlZeroMemory((PVOID)EndOfHeaders, Slack);
+ }
+
+ /* Get the section virtual size and the raw size */
+ SectionSize = Section->Misc.VirtualSize;
+ RawSize = Section->SizeOfRawData;
+
+ /* Safely align the raw size by 2 */
+ Status = RtlULongAdd(RawSize, 1, &AlignSize);
+ if (!NT_SUCCESS(Status))
+ {
+ goto Quickie;
+ }
+ AlignSize = ALIGN_DOWN_BY(AlignSize, 2);
+
+ /* IF we don't have a virtual size, use the raw size */
+ if (!SectionSize)
+ {
+ SectionSize = RawSize;
+ }
+
+ /* If we don't have raw data, ignore the raw size */
+ if (!Section->PointerToRawData)
+ {
+ RawSize = 0;
+ }
+ else if (SectionSize < RawSize)
+ {
+ /* And if the virtual size is smaller, use it as the final size */
+ RawSize = SectionSize;
+ }
+
+ /* Make sure that the section doesn't overflow in memory */
+ Status = RtlULongAdd(Section->VirtualAddress,
+ SectionSize,
+ &SectionEnd);
+ if (!NT_SUCCESS(Status))
+ {
+ Status = STATUS_INVALID_IMAGE_FORMAT;
+ goto Quickie;
+ }
+
+ /* Make sure that it fits within the image */
+ if (VirtualSize < SectionEnd)
+ {
+ Status = STATUS_INVALID_IMAGE_FORMAT;
+ goto Quickie;
+ }
+
+ /* Make sure it doesn't overflow on disk */
+ Status = RtlULongAdd(Section->VirtualAddress,
+ AlignSize,
+ &SectionEnd);
+ if (!NT_SUCCESS(Status))
+ {
+ Status = STATUS_INVALID_IMAGE_FORMAT;
+ goto Quickie;
+ }
+
+ /* Make sure that it fits within the disk image as well */
+ if (VirtualSize < SectionEnd)
+ {
+ Status = STATUS_INVALID_IMAGE_FORMAT;
+ goto Quickie;
+ }
+
+ /* So does this section have a valid size after all? */
+ if (RawSize)
+ {
+ /* Are we in the first iteration? */
+ if (!First)
+ {
+ /* Yes, read the section data */
+ Status = ImgpReadAtFileOffset(LocalFile,
+ AlignSize,
+ Section->PointerToRawData,
+ (PVOID)SectionStart,
+ NULL);
+ if (!NT_SUCCESS(Status))
+ {
+ goto Quickie;
+ }
+
+ /* Update our current offset */
+ Offset = AlignSize + Section->PointerToRawData;
+
+ /* Update the checksum to include this section */
+ PartialSum = BlUtlCheckSum(PartialSum,
+ (PUCHAR)SectionStart,
+ AlignSize,
+ 0x10002);
+ }
+ }
+
+ /* Are we in the first iteration? */
+ if (!First)
+ {
+ /* Is there space at the end of the section? */
+ if (RawSize < SectionSize)
+ {
+ /* Zero out the slack space that's there */
+ Slack = SectionSize - RawSize;
+ RtlZeroMemory((PVOID)(SectionStart + RawSize), Slack);
+ }
+
+ /* Update our tail offset */
+ EndOfHeaders = SectionStart + SectionSize;
+ }
+
+ /* Move to the next section */
+ Section++;
+ }
+
+ /* Are we in the first iteration? */
+ if (!First)
+ {
+ /* Go to the end of the file */
+ SectionStart = (ULONG_PTR)VirtualAddress + VirtualSize;
+
+ /* Is there still some slack space left? */
+ if (EndOfHeaders < SectionStart)
+ {
+ /* Zero it out */
+ Slack = SectionStart - EndOfHeaders;
+ RtlZeroMemory((PVOID)EndOfHeaders, Slack);
+ }
+ }
+
+ /* Did the first iteration complete OK? */
+ if ((NT_SUCCESS(Status)) && !(First))
+ {
+ /* Check how many non-image bytes are left in the file */
+ RemainingLength = FileSize - Offset;
+ while (RemainingLength)
+ {
+ /* See if the read will fit into our local buffer */
+ if (RemainingLength >= sizeof(LocalBuffer))
+ {
+ /* Nope, cap it */
+ BytesRead = sizeof(LocalBuffer);
+ }
+ else
+ {
+ /* Yes, but there's less to read */
+ BytesRead = RemainingLength;
+ }
+
+ /* Read 1024 bytes into the local buffer */
+ Status = ImgpReadAtFileOffset(LocalFile,
+ BytesRead,
+ Offset,
+ LocalBuffer,
+ &BytesRead);
+ if (!(NT_SUCCESS(Status)) || !(BytesRead))
+ {
+ Status = STATUS_FILE_INVALID;
+ goto Quickie;
+ }
+
+ /* Advance the offset and reduce the length */
+ RemainingLength -= BytesRead;
+ Offset += BytesRead;
+
+ /* Compute the checksum of this leftover space */
+ PartialSum = BlUtlCheckSum(PartialSum,
+ LocalBuffer,
+ BytesRead,
+ 0x10002);
+ }
+
+ /* Finally, calculate the final checksum and compare it */
+ FinalSum = FileSize + PartialSum;
+ if ((FinalSum != CheckSum) && (PartialSum == 0xFFFF))
+ {
+ /* It hit overflow, so set it to the file size */
+ FinalSum = FileSize;
+ }
+
+ /* If the checksum doesn't match, and caller is enforcing, bail out */
+ EfiPrintf(L"Final checksum: %lx. Original: %lx\r\n", FinalSum, CheckSum);
+ if ((FinalSum != CheckSum) && !(Flags & 0x10000))
+ {
+ Status = STATUS_IMAGE_CHECKSUM_MISMATCH;
+ goto Quickie;
+ }
+ }
+
EfiPrintf(L"MORE PE TODO: %lx\r\n", NtHeaders->OptionalHeader.AddressOfEntryPoint);
EfiStall(100000000);