X-Git-Url: https://git.proxmox.com/?a=blobdiff_plain;f=Tools%2FSource%2FTianoTools%2FFwImage%2Ffwimage.c;h=0097a945507b25a1dc9b7313aa68d7fad6980a54;hb=9bae46a555d20b2e4c0bc16dae260a5dc6372394;hp=e2e0d49b9f4b711d6789d4cbd98ee42cfb9615da;hpb=878ddf1fc3540a715f63594ed22b6929e881afb4;p=mirror_edk2.git diff --git a/Tools/Source/TianoTools/FwImage/fwimage.c b/Tools/Source/TianoTools/FwImage/fwimage.c index e2e0d49b9f..0097a94550 100644 --- a/Tools/Source/TianoTools/FwImage/fwimage.c +++ b/Tools/Source/TianoTools/FwImage/fwimage.c @@ -19,7 +19,8 @@ Abstract: --*/ -#include +#include "WinNtInclude.h" + #ifndef __GNUC__ #include #endif @@ -28,11 +29,11 @@ Abstract: #include #include -#include -#include -#include -#include -#include +#include +#include + +#include "CommonLib.h" +#include "EfiUtilityMsgs.c" #define UTILITY_NAME "FwImage" @@ -48,7 +49,7 @@ Usage ( VOID ) { - printf ("Usage: " UTILITY_NAME " {-t time-date} [APPLICATION|BS_DRIVER|RT_DRIVER|SAL_RT_DRIVER|COMBINED_PEIM_DRIVER|SECURITY_CORE|PEI_CORE|PE32_PEIM|RELOCATABLE_PEIM] peimage [outimage]"); + printf ("Usage: " UTILITY_NAME " {-t time-date} [BASE|SEC|PEI_CORE|PEIM|DXE_CORE|DXE_DRIVER|DXE_RUNTIME_DRIVER|DXE_SAL_DRIVER|DXE_SMM_DRIVER|TOOL|UEFI_DRIVER|UEFI_APPLICATION|USER_DEFINED] peimage [outimage]"); } static @@ -89,6 +90,40 @@ FCopyFile ( return STATUS_SUCCESS; } +static +STATUS +FReadFile ( + FILE *in, + VOID **Buffer, + UINTN *Length + ) +{ + fseek (in, 0, SEEK_END); + *Length = ftell (in); + *Buffer = malloc (*Length); + fseek (in, 0, SEEK_SET); + fread (*Buffer, *Length, 1, in); + return STATUS_SUCCESS; +} + +static +STATUS +FWriteFile ( + FILE *out, + VOID *Buffer, + UINTN Length + ) +{ + fseek (out, 0, SEEK_SET); + fwrite (Buffer, Length, 1, out); + if ((ULONG) ftell (out) != Length) { + Error (NULL, 0, 0, "write error", NULL); + return STATUS_ERROR; + } + free (Buffer); + return STATUS_SUCCESS; +} + int main ( int argc, @@ -119,13 +154,22 @@ Returns: UCHAR outname[500]; FILE *fpIn; FILE *fpOut; - EFI_IMAGE_DOS_HEADER DosHdr; - EFI_IMAGE_NT_HEADERS PeHdr; + VOID *ZeroBuffer; + EFI_IMAGE_DOS_HEADER *DosHdr; + EFI_IMAGE_NT_HEADERS *PeHdr; + EFI_IMAGE_OPTIONAL_HEADER32 *Optional32; + EFI_IMAGE_OPTIONAL_HEADER64 *Optional64; time_t TimeStamp; struct tm TimeStruct; EFI_IMAGE_DOS_HEADER BackupDosHdr; ULONG Index; + ULONG Index1; BOOLEAN TimeStampPresent; + UINTN AllignedRelocSize; + UINTN Delta; + EFI_IMAGE_SECTION_HEADER *SectionHeader; + UINT8 *FileBuffer; + UINTN FileLength; SetUtilityName (UTILITY_NAME); // @@ -200,33 +244,39 @@ Returns: p += 1; } - if (stricmp (p, "app") == 0 || stricmp (p, "APPLICATION") == 0) { + if (stricmp (p, "app") == 0 || stricmp (p, "UEFI_APPLICATION") == 0) { Type = EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION; Ext = ".efi"; - } else if (stricmp (p, "bsdrv") == 0 || stricmp (p, "BS_DRIVER") == 0) { + } else if (stricmp (p, "bsdrv") == 0 || stricmp (p, "DXE_DRIVER") == 0) { Type = EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER; Ext = ".efi"; - } else if (stricmp (p, "rtdrv") == 0 || stricmp (p, "RT_DRIVER") == 0) { + } else if (stricmp (p, "rtdrv") == 0 || stricmp (p, "DXE_RUNTIME_DRIVER") == 0) { Type = EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER; Ext = ".efi"; - } else if (stricmp (p, "rtdrv") == 0 || stricmp (p, "SAL_RT_DRIVER") == 0) { + } else if (stricmp (p, "rtdrv") == 0 || stricmp (p, "DXE_SAL_DRIVER") == 0) { Type = EFI_IMAGE_SUBSYSTEM_SAL_RUNTIME_DRIVER; Ext = ".efi"; - } else if (stricmp (p, "SECURITY_CORE") == 0) { + } else if (stricmp (p, "SEC") == 0) { Type = EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER; Ext = ".sec"; } else if (stricmp (p, "peim") == 0 || + stricmp (p, "BASE") == 0 || stricmp (p, "PEI_CORE") == 0 || - stricmp (p, "PE32_PEIM") == 0 || - stricmp (p, "RELOCATABLE_PEIM") == 0 || - stricmp (p, "combined_peim_driver") == 0 + stricmp (p, "PEIM") == 0 || + stricmp (p, "DXE_SMM_DRIVER") == 0 || + stricmp (p, "TOOL") == 0 || + stricmp (p, "UEFI_APPLICATION") == 0 || + stricmp (p, "USER_DEFINED") == 0 || + stricmp (p, "UEFI_DRIVER") == 0 || + stricmp (p, "DXE_CORE") == 0 ) { Type = EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER; Ext = ".pei"; } else { + printf ("%s", p); Usage (); return STATUS_ERROR; } @@ -238,24 +288,26 @@ Returns: Error (NULL, 0, 0, argv[2], "failed to open input file for reading"); return STATUS_ERROR; } + + FReadFile (fpIn, (VOID **)&FileBuffer, &FileLength); + // // Read the dos & pe hdrs of the image // - fseek (fpIn, 0, SEEK_SET); - fread (&DosHdr, sizeof (DosHdr), 1, fpIn); - if (DosHdr.e_magic != EFI_IMAGE_DOS_SIGNATURE) { + DosHdr = (EFI_IMAGE_DOS_HEADER *)FileBuffer; + if (DosHdr->e_magic != EFI_IMAGE_DOS_SIGNATURE) { Error (NULL, 0, 0, argv[2], "DOS header signature not found in source image"); fclose (fpIn); return STATUS_ERROR; } - fseek (fpIn, DosHdr.e_lfanew, SEEK_SET); - fread (&PeHdr, sizeof (PeHdr), 1, fpIn); - if (PeHdr.Signature != EFI_IMAGE_NT_SIGNATURE) { + PeHdr = (EFI_IMAGE_NT_HEADERS *)(FileBuffer + DosHdr->e_lfanew); + if (PeHdr->Signature != EFI_IMAGE_NT_SIGNATURE) { Error (NULL, 0, 0, argv[2], "PE header signature not found in source image"); fclose (fpIn); return STATUS_ERROR; } + // // open output file // @@ -283,42 +335,173 @@ Returns: fclose (fpIn); return STATUS_ERROR; } - // - // Copy the file - // - if (FCopyFile (fpIn, fpOut) != STATUS_SUCCESS) { - fclose (fpIn); - fclose (fpOut); - return STATUS_ERROR; - } + // // Zero all unused fields of the DOS header // - memcpy (&BackupDosHdr, &DosHdr, sizeof (DosHdr)); - memset (&DosHdr, 0, sizeof (DosHdr)); - DosHdr.e_magic = BackupDosHdr.e_magic; - DosHdr.e_lfanew = BackupDosHdr.e_lfanew; - fseek (fpOut, 0, SEEK_SET); - fwrite (&DosHdr, sizeof (DosHdr), 1, fpOut); - - fseek (fpOut, sizeof (DosHdr), SEEK_SET); - for (Index = sizeof (DosHdr); Index < (ULONG) DosHdr.e_lfanew; Index++) { - fwrite (&DosHdr.e_cp, 1, 1, fpOut); + memcpy (&BackupDosHdr, DosHdr, sizeof (EFI_IMAGE_DOS_HEADER)); + memset (DosHdr, 0, sizeof (EFI_IMAGE_DOS_HEADER)); + DosHdr->e_magic = BackupDosHdr.e_magic; + DosHdr->e_lfanew = BackupDosHdr.e_lfanew; + + for (Index = sizeof (EFI_IMAGE_DOS_HEADER); Index < (ULONG) DosHdr->e_lfanew; Index++) { + FileBuffer[Index] = DosHdr->e_cp; } + // // Path the PE header // - PeHdr.OptionalHeader.Subsystem = (USHORT) Type; + PeHdr->OptionalHeader.Subsystem = (USHORT) Type; if (TimeStampPresent) { - PeHdr.FileHeader.TimeDateStamp = (UINT32) TimeStamp; + PeHdr->FileHeader.TimeDateStamp = (UINT32) TimeStamp; + } + + if (PeHdr->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) { + Optional32 = (EFI_IMAGE_OPTIONAL_HEADER32 *)&PeHdr->OptionalHeader; + Optional32->MajorLinkerVersion = 0; + Optional32->MinorLinkerVersion = 0; + Optional32->MajorOperatingSystemVersion = 0; + Optional32->MinorOperatingSystemVersion = 0; + Optional32->MajorImageVersion = 0; + Optional32->MinorImageVersion = 0; + Optional32->MajorSubsystemVersion = 0; + Optional32->MinorSubsystemVersion = 0; + Optional32->Win32VersionValue = 0; + Optional32->CheckSum = 0; + Optional32->SizeOfStackReserve = 0; + Optional32->SizeOfStackCommit = 0; + Optional32->SizeOfHeapReserve = 0; + Optional32->SizeOfHeapCommit = 0; + + // + // Zero the .pdata section if the machine type is X64 and the Debug Directoty entry is empty + // + if (PeHdr->FileHeader.Machine == 0x8664) { // X64 + if (Optional32->NumberOfRvaAndSizes >= 4) { + if (Optional32->NumberOfRvaAndSizes < 7 || (Optional32->NumberOfRvaAndSizes >= 7 && Optional32->DataDirectory[6].Size == 0)) { + SectionHeader = (EFI_IMAGE_SECTION_HEADER *)(FileBuffer + DosHdr->e_lfanew + sizeof(UINT32) + sizeof (EFI_IMAGE_FILE_HEADER) + PeHdr->FileHeader.SizeOfOptionalHeader); + for (Index = 0; Index < PeHdr->FileHeader.NumberOfSections; Index++, SectionHeader++) { + if (SectionHeader->VirtualAddress == Optional32->DataDirectory[3].VirtualAddress) { + for (Index1 = 0; Index1 < Optional32->DataDirectory[3].Size; Index1++) { + FileBuffer[SectionHeader->PointerToRawData + Index1] = 0; + } + } + } + Optional32->DataDirectory[3].Size = 0; + Optional32->DataDirectory[3].VirtualAddress = 0; + } + } + } + + // + // Strip zero padding at the end of the .reloc section + // + if (Optional32->NumberOfRvaAndSizes >= 6) { + if (Optional32->DataDirectory[5].Size != 0) { + SectionHeader = (EFI_IMAGE_SECTION_HEADER *)(FileBuffer + DosHdr->e_lfanew + sizeof(UINT32) + sizeof (EFI_IMAGE_FILE_HEADER) + PeHdr->FileHeader.SizeOfOptionalHeader); + for (Index = 0; Index < PeHdr->FileHeader.NumberOfSections; Index++, SectionHeader++) { + // + // Look for the Section Header that starts as the same virtual address as the Base Relocation Data Directory + // + if (SectionHeader->VirtualAddress == Optional32->DataDirectory[5].VirtualAddress) { + SectionHeader->Misc.VirtualSize = Optional32->DataDirectory[5].Size; + AllignedRelocSize = (Optional32->DataDirectory[5].Size + Optional32->FileAlignment - 1) & (~(Optional32->FileAlignment - 1)); + // + // Check to see if there is zero padding at the end of the base relocations + // + if (AllignedRelocSize < SectionHeader->SizeOfRawData) { + // + // Check to see if the base relocations are at the end of the file + // + if (SectionHeader->PointerToRawData + SectionHeader->SizeOfRawData == Optional32->SizeOfImage) { + // + // All the required conditions are met to strip the zero padding of the end of the base relocations section + // + Optional32->SizeOfImage -= (SectionHeader->SizeOfRawData - AllignedRelocSize); + Optional32->SizeOfInitializedData -= (SectionHeader->SizeOfRawData - AllignedRelocSize); + SectionHeader->SizeOfRawData = AllignedRelocSize; + FileLength = Optional32->SizeOfImage; + } + } + } + } + } + } + } + if (PeHdr->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC) { + Optional64 = (EFI_IMAGE_OPTIONAL_HEADER64 *)&PeHdr->OptionalHeader; + Optional64->MajorLinkerVersion = 0; + Optional64->MinorLinkerVersion = 0; + Optional64->MajorOperatingSystemVersion = 0; + Optional64->MinorOperatingSystemVersion = 0; + Optional64->MajorImageVersion = 0; + Optional64->MinorImageVersion = 0; + Optional64->MajorSubsystemVersion = 0; + Optional64->MinorSubsystemVersion = 0; + Optional64->Win32VersionValue = 0; + Optional64->CheckSum = 0; + Optional64->SizeOfStackReserve = 0; + Optional64->SizeOfStackCommit = 0; + Optional64->SizeOfHeapReserve = 0; + Optional64->SizeOfHeapCommit = 0; + + // + // Zero the .pdata section if the machine type is X64 and the Debug Directory is empty + // + if (PeHdr->FileHeader.Machine == 0x8664) { // X64 + if (Optional64->NumberOfRvaAndSizes >= 4) { + if (Optional64->NumberOfRvaAndSizes < 7 || (Optional64->NumberOfRvaAndSizes >= 7 && Optional64->DataDirectory[6].Size == 0)) { + SectionHeader = (EFI_IMAGE_SECTION_HEADER *)(FileBuffer + DosHdr->e_lfanew + sizeof(UINT32) + sizeof (EFI_IMAGE_FILE_HEADER) + PeHdr->FileHeader.SizeOfOptionalHeader); + for (Index = 0; Index < PeHdr->FileHeader.NumberOfSections; Index++, SectionHeader++) { + if (SectionHeader->VirtualAddress == Optional64->DataDirectory[3].VirtualAddress) { + for (Index1 = 0; Index1 < Optional64->DataDirectory[3].Size; Index1++) { + FileBuffer[SectionHeader->PointerToRawData + Index1] = 0; + } + } + } + Optional64->DataDirectory[3].Size = 0; + Optional64->DataDirectory[3].VirtualAddress = 0; + } + } + } + + // + // Strip zero padding at the end of the .reloc section + // + if (Optional64->NumberOfRvaAndSizes >= 6) { + if (Optional64->DataDirectory[5].Size != 0) { + SectionHeader = (EFI_IMAGE_SECTION_HEADER *)(FileBuffer + DosHdr->e_lfanew + sizeof(UINT32) + sizeof (EFI_IMAGE_FILE_HEADER) + PeHdr->FileHeader.SizeOfOptionalHeader); + for (Index = 0; Index < PeHdr->FileHeader.NumberOfSections; Index++, SectionHeader++) { + // + // Look for the Section Header that starts as the same virtual address as the Base Relocation Data Directory + // + if (SectionHeader->VirtualAddress == Optional64->DataDirectory[5].VirtualAddress) { + SectionHeader->Misc.VirtualSize = Optional64->DataDirectory[5].Size; + AllignedRelocSize = (Optional64->DataDirectory[5].Size + Optional64->FileAlignment - 1) & (~(Optional64->FileAlignment - 1)); + // + // Check to see if there is zero padding at the end of the base relocations + // + if (AllignedRelocSize < SectionHeader->SizeOfRawData) { + // + // Check to see if the base relocations are at the end of the file + // + if (SectionHeader->PointerToRawData + SectionHeader->SizeOfRawData == Optional64->SizeOfImage) { + // + // All the required conditions are met to strip the zero padding of the end of the base relocations section + // + Optional64->SizeOfImage -= (SectionHeader->SizeOfRawData - AllignedRelocSize); + Optional64->SizeOfInitializedData -= (SectionHeader->SizeOfRawData - AllignedRelocSize); + SectionHeader->SizeOfRawData = AllignedRelocSize; + FileLength = Optional64->SizeOfImage; + } + } + } + } + } + } } - PeHdr.OptionalHeader.SizeOfStackReserve = 0; - PeHdr.OptionalHeader.SizeOfStackCommit = 0; - PeHdr.OptionalHeader.SizeOfHeapReserve = 0; - PeHdr.OptionalHeader.SizeOfHeapCommit = 0; - fseek (fpOut, DosHdr.e_lfanew, SEEK_SET); - fwrite (&PeHdr, sizeof (PeHdr), 1, fpOut); + FWriteFile (fpOut, FileBuffer, FileLength); // // Done