+++ /dev/null
-/*++\r
-\r
-Copyright (c) 2004, Intel Corporation \r
-All rights reserved. This program and the accompanying materials \r
-are licensed and made available under the terms and conditions of the BSD License \r
-which accompanies this distribution. The full text of the license may be found at \r
-http://opensource.org/licenses/bsd-license.php \r
- \r
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. \r
-\r
-Module Name:\r
-\r
- fwimage.c\r
-\r
-Abstract:\r
-\r
- Converts a pe32+ image to an FW image type\r
-\r
---*/\r
-\r
-#include "WinNtInclude.h"\r
-\r
-#ifndef __GNUC__\r
-#include <windows.h>\r
-#endif\r
-#include <stdio.h>\r
-#include <stdlib.h>\r
-#include <string.h>\r
-#include <time.h>\r
-\r
-#include <Common/UefiBaseTypes.h>\r
-#include <Common/EfiImage.h>\r
-\r
-#include "CommonLib.h"\r
-#include "EfiUtilityMsgs.c"\r
-\r
-#define UTILITY_NAME "FwImage"\r
-\r
-#ifdef __GNUC__\r
-typedef unsigned long ULONG;\r
-typedef unsigned char UCHAR;\r
-typedef unsigned char *PUCHAR;\r
-typedef unsigned short USHORT;\r
-#endif\r
-\r
-VOID\r
-Usage (\r
- VOID\r
- )\r
-{\r
- 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]");\r
-}\r
-\r
-static\r
-STATUS\r
-FCopyFile (\r
- FILE *in,\r
- FILE *out\r
- )\r
-{\r
- ULONG filesize;\r
- ULONG offset;\r
- ULONG length;\r
- UCHAR Buffer[8 * 1024];\r
-\r
- fseek (in, 0, SEEK_END);\r
- filesize = ftell (in);\r
-\r
- fseek (in, 0, SEEK_SET);\r
- fseek (out, 0, SEEK_SET);\r
-\r
- offset = 0;\r
- while (offset < filesize) {\r
- length = sizeof (Buffer);\r
- if (filesize - offset < length) {\r
- length = filesize - offset;\r
- }\r
-\r
- fread (Buffer, length, 1, in);\r
- fwrite (Buffer, length, 1, out);\r
- offset += length;\r
- }\r
-\r
- if ((ULONG) ftell (out) != filesize) {\r
- Error (NULL, 0, 0, "write error", NULL);\r
- return STATUS_ERROR;\r
- }\r
-\r
- return STATUS_SUCCESS;\r
-}\r
-\r
-static\r
-STATUS\r
-FReadFile (\r
- FILE *in,\r
- VOID **Buffer,\r
- UINTN *Length\r
- )\r
-{\r
- fseek (in, 0, SEEK_END);\r
- *Length = ftell (in);\r
- *Buffer = malloc (*Length);\r
- fseek (in, 0, SEEK_SET);\r
- fread (*Buffer, *Length, 1, in);\r
- return STATUS_SUCCESS;\r
-}\r
-\r
-static\r
-STATUS\r
-FWriteFile (\r
- FILE *out,\r
- VOID *Buffer,\r
- UINTN Length\r
- )\r
-{\r
- fseek (out, 0, SEEK_SET);\r
- fwrite (Buffer, Length, 1, out);\r
- if ((ULONG) ftell (out) != Length) {\r
- Error (NULL, 0, 0, "write error", NULL);\r
- return STATUS_ERROR;\r
- }\r
- free (Buffer);\r
- return STATUS_SUCCESS;\r
-}\r
-\r
-int\r
-main (\r
- int argc,\r
- char *argv[]\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- Main function.\r
-\r
-Arguments:\r
-\r
- argc - Number of command line parameters.\r
- argv - Array of pointers to command line parameter strings.\r
-\r
-Returns:\r
- STATUS_SUCCESS - Utility exits successfully.\r
- STATUS_ERROR - Some error occurred during execution.\r
-\r
---*/\r
-{\r
- ULONG Type;\r
- PUCHAR Ext;\r
- PUCHAR p;\r
- PUCHAR pe;\r
- PUCHAR OutImageName;\r
- UCHAR outname[500];\r
- FILE *fpIn;\r
- FILE *fpOut;\r
- VOID *ZeroBuffer;\r
- EFI_IMAGE_DOS_HEADER *DosHdr;\r
- EFI_IMAGE_NT_HEADERS *PeHdr;\r
- EFI_IMAGE_OPTIONAL_HEADER32 *Optional32;\r
- EFI_IMAGE_OPTIONAL_HEADER64 *Optional64;\r
- time_t TimeStamp;\r
- struct tm TimeStruct;\r
- EFI_IMAGE_DOS_HEADER BackupDosHdr;\r
- ULONG Index;\r
- ULONG Index1;\r
- ULONG Index2;\r
- ULONG Index3;\r
- BOOLEAN TimeStampPresent;\r
- UINTN AllignedRelocSize;\r
- UINTN Delta;\r
- EFI_IMAGE_SECTION_HEADER *SectionHeader;\r
- UINT8 *FileBuffer;\r
- UINTN FileLength;\r
- RUNTIME_FUNCTION *RuntimeFunction;\r
- UNWIND_INFO *UnwindInfo;\r
-\r
- SetUtilityName (UTILITY_NAME);\r
- //\r
- // Assign to fix compile warning\r
- //\r
- OutImageName = NULL;\r
- Type = 0;\r
- Ext = 0;\r
- TimeStamp = 0;\r
- TimeStampPresent = FALSE;\r
-\r
- //\r
- // Look for -t time-date option first. If the time is "0", then\r
- // skip it.\r
- //\r
- if ((argc > 2) && !strcmp (argv[1], "-t")) {\r
- TimeStampPresent = TRUE;\r
- if (strcmp (argv[2], "0") != 0) {\r
- //\r
- // Convert the string to a value\r
- //\r
- memset ((char *) &TimeStruct, 0, sizeof (TimeStruct));\r
- if (sscanf(\r
- argv[2], "%d/%d/%d,%d:%d:%d",\r
- &TimeStruct.tm_mon, /* months since January - [0,11] */\r
- &TimeStruct.tm_mday, /* day of the month - [1,31] */\r
- &TimeStruct.tm_year, /* years since 1900 */\r
- &TimeStruct.tm_hour, /* hours since midnight - [0,23] */\r
- &TimeStruct.tm_min, /* minutes after the hour - [0,59] */\r
- &TimeStruct.tm_sec /* seconds after the minute - [0,59] */\r
- ) != 6) {\r
- Error (NULL, 0, 0, argv[2], "failed to convert to mm/dd/yyyy,hh:mm:ss format");\r
- return STATUS_ERROR;\r
- }\r
- //\r
- // Now fixup some of the fields\r
- //\r
- TimeStruct.tm_mon--;\r
- TimeStruct.tm_year -= 1900;\r
- //\r
- // Sanity-check values?\r
- // Convert\r
- //\r
- TimeStamp = mktime (&TimeStruct);\r
- if (TimeStamp == (time_t) - 1) {\r
- Error (NULL, 0, 0, argv[2], "failed to convert time");\r
- return STATUS_ERROR;\r
- }\r
- }\r
- //\r
- // Skip over the args\r
- //\r
- argc -= 2;\r
- argv += 2;\r
- }\r
- //\r
- // Check for enough args\r
- //\r
- if (argc < 3) {\r
- Usage ();\r
- return STATUS_ERROR;\r
- }\r
-\r
- if (argc == 4) {\r
- OutImageName = argv[3];\r
- }\r
- //\r
- // Get new image type\r
- //\r
- p = argv[1];\r
- if (*p == '/' || *p == '\\') {\r
- p += 1;\r
- }\r
-\r
- if (stricmp (p, "app") == 0 || stricmp (p, "UEFI_APPLICATION") == 0) {\r
- Type = EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION;\r
- Ext = ".efi";\r
-\r
- } else if (stricmp (p, "bsdrv") == 0 || stricmp (p, "DXE_DRIVER") == 0) {\r
- Type = EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER;\r
- Ext = ".efi";\r
-\r
- } else if (stricmp (p, "rtdrv") == 0 || stricmp (p, "DXE_RUNTIME_DRIVER") == 0) {\r
- Type = EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER;\r
- Ext = ".efi";\r
-\r
- } else if (stricmp (p, "rtdrv") == 0 || stricmp (p, "DXE_SAL_DRIVER") == 0) {\r
- Type = EFI_IMAGE_SUBSYSTEM_SAL_RUNTIME_DRIVER;\r
- Ext = ".efi";\r
- } else if (stricmp (p, "SEC") == 0) {\r
- Type = EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER;\r
- Ext = ".sec";\r
- } else if (stricmp (p, "peim") == 0 ||\r
- stricmp (p, "BASE") == 0 ||\r
- stricmp (p, "PEI_CORE") == 0 ||\r
- stricmp (p, "PEIM") == 0 ||\r
- stricmp (p, "DXE_SMM_DRIVER") == 0 ||\r
- stricmp (p, "TOOL") == 0 ||\r
- stricmp (p, "UEFI_APPLICATION") == 0 ||\r
- stricmp (p, "USER_DEFINED") == 0 ||\r
- stricmp (p, "UEFI_DRIVER") == 0 ||\r
- stricmp (p, "DXE_CORE") == 0\r
- ) {\r
- Type = EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER;\r
- Ext = ".pei";\r
- } else {\r
- printf ("%s", p);\r
- Usage ();\r
- return STATUS_ERROR;\r
- }\r
- //\r
- // open source file\r
- //\r
- fpIn = fopen (argv[2], "rb");\r
- if (!fpIn) {\r
- Error (NULL, 0, 0, argv[2], "failed to open input file for reading");\r
- return STATUS_ERROR;\r
- }\r
-\r
- FReadFile (fpIn, (VOID **)&FileBuffer, &FileLength);\r
-\r
- //\r
- // Read the dos & pe hdrs of the image\r
- //\r
- DosHdr = (EFI_IMAGE_DOS_HEADER *)FileBuffer;\r
- if (DosHdr->e_magic != EFI_IMAGE_DOS_SIGNATURE) {\r
- Error (NULL, 0, 0, argv[2], "DOS header signature not found in source image");\r
- fclose (fpIn);\r
- return STATUS_ERROR;\r
- }\r
-\r
- PeHdr = (EFI_IMAGE_NT_HEADERS *)(FileBuffer + DosHdr->e_lfanew);\r
- if (PeHdr->Signature != EFI_IMAGE_NT_SIGNATURE) {\r
- Error (NULL, 0, 0, argv[2], "PE header signature not found in source image");\r
- fclose (fpIn);\r
- return STATUS_ERROR;\r
- }\r
-\r
- //\r
- // open output file\r
- //\r
- strcpy (outname, argv[2]);\r
- pe = NULL;\r
- for (p = outname; *p; p++) {\r
- if (*p == '.') {\r
- pe = p;\r
- }\r
- }\r
-\r
- if (!pe) {\r
- pe = p;\r
- }\r
-\r
- strcpy (pe, Ext);\r
-\r
- if (!OutImageName) {\r
- OutImageName = outname;\r
- }\r
-\r
- fpOut = fopen (OutImageName, "w+b");\r
- if (!fpOut) {\r
- Error (NULL, 0, 0, OutImageName, "could not open output file for writing");\r
- fclose (fpIn);\r
- return STATUS_ERROR;\r
- }\r
-\r
- //\r
- // Zero all unused fields of the DOS header\r
- //\r
- memcpy (&BackupDosHdr, DosHdr, sizeof (EFI_IMAGE_DOS_HEADER));\r
- memset (DosHdr, 0, sizeof (EFI_IMAGE_DOS_HEADER));\r
- DosHdr->e_magic = BackupDosHdr.e_magic;\r
- DosHdr->e_lfanew = BackupDosHdr.e_lfanew;\r
-\r
- for (Index = sizeof (EFI_IMAGE_DOS_HEADER); Index < (ULONG) DosHdr->e_lfanew; Index++) {\r
- FileBuffer[Index] = DosHdr->e_cp;\r
- }\r
-\r
- //\r
- // Path the PE header\r
- //\r
- PeHdr->OptionalHeader.Subsystem = (USHORT) Type;\r
- if (TimeStampPresent) {\r
- PeHdr->FileHeader.TimeDateStamp = (UINT32) TimeStamp;\r
- }\r
-\r
- if (PeHdr->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
- Optional32 = (EFI_IMAGE_OPTIONAL_HEADER32 *)&PeHdr->OptionalHeader;\r
- Optional32->MajorLinkerVersion = 0;\r
- Optional32->MinorLinkerVersion = 0;\r
- Optional32->MajorOperatingSystemVersion = 0;\r
- Optional32->MinorOperatingSystemVersion = 0;\r
- Optional32->MajorImageVersion = 0;\r
- Optional32->MinorImageVersion = 0;\r
- Optional32->MajorSubsystemVersion = 0;\r
- Optional32->MinorSubsystemVersion = 0;\r
- Optional32->Win32VersionValue = 0;\r
- Optional32->CheckSum = 0;\r
- Optional32->SizeOfStackReserve = 0;\r
- Optional32->SizeOfStackCommit = 0;\r
- Optional32->SizeOfHeapReserve = 0;\r
- Optional32->SizeOfHeapCommit = 0;\r
-\r
- //\r
- // Strip zero padding at the end of the .reloc section \r
- //\r
- if (Optional32->NumberOfRvaAndSizes >= 6) {\r
- if (Optional32->DataDirectory[5].Size != 0) {\r
- SectionHeader = (EFI_IMAGE_SECTION_HEADER *)(FileBuffer + DosHdr->e_lfanew + sizeof(UINT32) + sizeof (EFI_IMAGE_FILE_HEADER) + PeHdr->FileHeader.SizeOfOptionalHeader);\r
- for (Index = 0; Index < PeHdr->FileHeader.NumberOfSections; Index++, SectionHeader++) {\r
- //\r
- // Look for the Section Header that starts as the same virtual address as the Base Relocation Data Directory\r
- //\r
- if (SectionHeader->VirtualAddress == Optional32->DataDirectory[5].VirtualAddress) {\r
- SectionHeader->Misc.VirtualSize = Optional32->DataDirectory[5].Size;\r
- AllignedRelocSize = (Optional32->DataDirectory[5].Size + Optional32->FileAlignment - 1) & (~(Optional32->FileAlignment - 1));\r
- //\r
- // Check to see if there is zero padding at the end of the base relocations\r
- //\r
- if (AllignedRelocSize < SectionHeader->SizeOfRawData) {\r
- //\r
- // Check to see if the base relocations are at the end of the file\r
- //\r
- if (SectionHeader->PointerToRawData + SectionHeader->SizeOfRawData == Optional32->SizeOfImage) {\r
- //\r
- // All the required conditions are met to strip the zero padding of the end of the base relocations section\r
- //\r
- Optional32->SizeOfImage -= (SectionHeader->SizeOfRawData - AllignedRelocSize);\r
- Optional32->SizeOfInitializedData -= (SectionHeader->SizeOfRawData - AllignedRelocSize);\r
- SectionHeader->SizeOfRawData = AllignedRelocSize;\r
- FileLength = Optional32->SizeOfImage;\r
- }\r
- }\r
- }\r
- }\r
- }\r
- }\r
- } \r
- if (PeHdr->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC) {\r
- Optional64 = (EFI_IMAGE_OPTIONAL_HEADER64 *)&PeHdr->OptionalHeader;\r
- Optional64->MajorLinkerVersion = 0;\r
- Optional64->MinorLinkerVersion = 0;\r
- Optional64->MajorOperatingSystemVersion = 0;\r
- Optional64->MinorOperatingSystemVersion = 0;\r
- Optional64->MajorImageVersion = 0;\r
- Optional64->MinorImageVersion = 0;\r
- Optional64->MajorSubsystemVersion = 0;\r
- Optional64->MinorSubsystemVersion = 0;\r
- Optional64->Win32VersionValue = 0;\r
- Optional64->CheckSum = 0;\r
- Optional64->SizeOfStackReserve = 0;\r
- Optional64->SizeOfStackCommit = 0;\r
- Optional64->SizeOfHeapReserve = 0;\r
- Optional64->SizeOfHeapCommit = 0;\r
-\r
- //\r
- // Zero the .pdata section if the machine type is X64 and the Debug Directory is empty\r
- //\r
- if (PeHdr->FileHeader.Machine == 0x8664) { // X64\r
- if (Optional64->NumberOfRvaAndSizes >= 4) {\r
- if (Optional64->NumberOfRvaAndSizes < 7 || (Optional64->NumberOfRvaAndSizes >= 7 && Optional64->DataDirectory[6].Size == 0)) {\r
- SectionHeader = (EFI_IMAGE_SECTION_HEADER *)(FileBuffer + DosHdr->e_lfanew + sizeof(UINT32) + sizeof (EFI_IMAGE_FILE_HEADER) + PeHdr->FileHeader.SizeOfOptionalHeader);\r
- for (Index = 0; Index < PeHdr->FileHeader.NumberOfSections; Index++, SectionHeader++) {\r
- if (SectionHeader->VirtualAddress == Optional64->DataDirectory[3].VirtualAddress) {\r
- RuntimeFunction = (RUNTIME_FUNCTION *)(FileBuffer + SectionHeader->PointerToRawData);\r
- for (Index1 = 0; Index1 < Optional64->DataDirectory[3].Size / sizeof (RUNTIME_FUNCTION); Index1++, RuntimeFunction++) {\r
- SectionHeader = (EFI_IMAGE_SECTION_HEADER *)(FileBuffer + DosHdr->e_lfanew + sizeof(UINT32) + sizeof (EFI_IMAGE_FILE_HEADER) + PeHdr->FileHeader.SizeOfOptionalHeader);\r
- for (Index2 = 0; Index2 < PeHdr->FileHeader.NumberOfSections; Index2++, SectionHeader++) {\r
- if (RuntimeFunction->UnwindInfoAddress > SectionHeader->VirtualAddress && RuntimeFunction->UnwindInfoAddress < (SectionHeader->VirtualAddress + SectionHeader->SizeOfRawData)) {\r
- UnwindInfo = (UNWIND_INFO *)(FileBuffer + SectionHeader->PointerToRawData + (RuntimeFunction->UnwindInfoAddress - SectionHeader->VirtualAddress));\r
- if (UnwindInfo->Version == 1) {\r
- memset (UnwindInfo + 1, 0, UnwindInfo->CountOfUnwindCodes * sizeof (UINT16));\r
- memset (UnwindInfo, 0, sizeof (UNWIND_INFO));\r
- }\r
- }\r
- }\r
- memset (RuntimeFunction, 0, sizeof (RUNTIME_FUNCTION));\r
- }\r
- }\r
- }\r
- Optional64->DataDirectory[3].Size = 0;\r
- Optional64->DataDirectory[3].VirtualAddress = 0;\r
- }\r
- }\r
- }\r
-\r
- //\r
- // Strip zero padding at the end of the .reloc section \r
- //\r
- if (Optional64->NumberOfRvaAndSizes >= 6) {\r
- if (Optional64->DataDirectory[5].Size != 0) {\r
- SectionHeader = (EFI_IMAGE_SECTION_HEADER *)(FileBuffer + DosHdr->e_lfanew + sizeof(UINT32) + sizeof (EFI_IMAGE_FILE_HEADER) + PeHdr->FileHeader.SizeOfOptionalHeader);\r
- for (Index = 0; Index < PeHdr->FileHeader.NumberOfSections; Index++, SectionHeader++) {\r
- //\r
- // Look for the Section Header that starts as the same virtual address as the Base Relocation Data Directory\r
- //\r
- if (SectionHeader->VirtualAddress == Optional64->DataDirectory[5].VirtualAddress) {\r
- SectionHeader->Misc.VirtualSize = Optional64->DataDirectory[5].Size;\r
- AllignedRelocSize = (Optional64->DataDirectory[5].Size + Optional64->FileAlignment - 1) & (~(Optional64->FileAlignment - 1));\r
- //\r
- // Check to see if there is zero padding at the end of the base relocations\r
- //\r
- if (AllignedRelocSize < SectionHeader->SizeOfRawData) {\r
- //\r
- // Check to see if the base relocations are at the end of the file\r
- //\r
- if (SectionHeader->PointerToRawData + SectionHeader->SizeOfRawData == Optional64->SizeOfImage) {\r
- //\r
- // All the required conditions are met to strip the zero padding of the end of the base relocations section\r
- //\r
- Optional64->SizeOfImage -= (SectionHeader->SizeOfRawData - AllignedRelocSize);\r
- Optional64->SizeOfInitializedData -= (SectionHeader->SizeOfRawData - AllignedRelocSize);\r
- SectionHeader->SizeOfRawData = AllignedRelocSize;\r
- FileLength = Optional64->SizeOfImage;\r
- }\r
- }\r
- }\r
- }\r
- }\r
- }\r
- }\r
-\r
- FWriteFile (fpOut, FileBuffer, FileLength);\r
-\r
- //\r
- // Done\r
- //\r
- fclose (fpIn);\r
- fclose (fpOut);\r
- //\r
- // printf ("Created %s\n", OutImageName);\r
- //\r
- return STATUS_SUCCESS;\r
-}\r