diff options
Diffstat (limited to 'Tools/CCode/Source/FwImage/fwimage.c')
-rw-r--r-- | Tools/CCode/Source/FwImage/fwimage.c | 1132 |
1 files changed, 0 insertions, 1132 deletions
diff --git a/Tools/CCode/Source/FwImage/fwimage.c b/Tools/CCode/Source/FwImage/fwimage.c deleted file mode 100644 index f51f824e22..0000000000 --- a/Tools/CCode/Source/FwImage/fwimage.c +++ /dev/null @@ -1,1132 +0,0 @@ -/*++
-
-Copyright (c) 2004 - 2007, Intel Corporation
-All rights reserved. This program and the accompanying materials
-are licensed and made available under the terms and conditions of the BSD License
-which accompanies this distribution. The full text of the license may be found at
-http://opensource.org/licenses/bsd-license.php
-
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
-
-Module Name:
-
- fwimage.c
-
-Abstract:
-
- Converts a pe32+ image to an FW image type
-
---*/
-
-#include "WinNtInclude.h"
-
-//
-// List of OS and CPU which support ELF to PE conversion
-//
-#if defined(linux) -#if defined (__i386__) || defined(__x86_64__) -#define HAVE_ELF -#endif -#endif - -#ifndef __GNUC__
-#include <windows.h>
-#endif
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <time.h>
- -#ifdef HAVE_ELF -#include <elf.h> -#endif -
-#include <Common/UefiBaseTypes.h>
-#include <Common/EfiImage.h>
-
-#include "CommonLib.h"
-#include "EfiUtilityMsgs.c"
-
-//
-// Version of this utility
-//
-#define UTILITY_NAME "FwImage"
-#define UTILITY_MAJOR_VERSION 1
-#define UTILITY_MINOR_VERSION 0
-
-#ifdef __GNUC__
-typedef unsigned long ULONG;
-typedef unsigned char UCHAR;
-typedef unsigned char *PUCHAR;
-typedef unsigned short USHORT;
-#endif
-
-PUCHAR InImageName;
-
-static
-void
-Version (
- VOID
- )
-{
- printf ("%s v%d.%d -EDK Utility for Converting a pe32+ image to an FW image type.\n", UTILITY_NAME, UTILITY_MAJOR_VERSION, UTILITY_MINOR_VERSION);
- printf ("Copyright (c) 1999-2006 Intel Corporation. All rights reserved.\n");
-}
-
-
-VOID
-Usage (
- VOID
- )
-{
- Version();
- printf ("\nUsage: " UTILITY_NAME " {-t time-date} {-h|--help|-?|/?|-V|--version} \n\
- [BASE|SEC|PEI_CORE|PEIM|DXE_CORE|DXE_DRIVER|DXE_RUNTIME_DRIVER|\n\
- DXE_SAL_DRIVER|DXE_SMM_DRIVER|TOOL|UEFI_DRIVER|UEFI_APPLICATION|\n\
- USER_DEFINED] peimage [outimage]\n");
-}
-
-static
-STATUS
-FCopyFile (
- FILE *in,
- FILE *out
- )
-{
- ULONG filesize;
- ULONG offset;
- ULONG length;
- UCHAR Buffer[8 * 1024];
-
- fseek (in, 0, SEEK_END);
- filesize = ftell (in);
-
- fseek (in, 0, SEEK_SET);
- fseek (out, 0, SEEK_SET);
-
- offset = 0;
- while (offset < filesize) {
- length = sizeof (Buffer);
- if (filesize - offset < length) {
- length = filesize - offset;
- }
-
- fread (Buffer, length, 1, in);
- fwrite (Buffer, length, 1, out);
- offset += length;
- }
-
- if ((ULONG) ftell (out) != filesize) {
- Error (NULL, 0, 0, "write error", NULL);
- return STATUS_ERROR;
- }
-
- 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;
-}
-
-#ifdef HAVE_ELF -INTN -IsElfHeader( - UINT8 *FileBuffer -) -{ - return (FileBuffer[EI_MAG0] == ELFMAG0 - && FileBuffer[EI_MAG1] == ELFMAG1 - && FileBuffer[EI_MAG2] == ELFMAG2 - && FileBuffer[EI_MAG3] == ELFMAG3); -} - -typedef Elf32_Shdr Elf_Shdr; -typedef Elf32_Ehdr Elf_Ehdr; -typedef Elf32_Rel Elf_Rel; -typedef Elf32_Sym Elf_Sym; -#define ELFCLASS ELFCLASS32 -#define ELF_R_TYPE(r) ELF32_R_TYPE(r) -#define ELF_R_SYM(r) ELF32_R_SYM(r) - -// -// Well known ELF structures. -// -Elf_Ehdr *Ehdr; -Elf_Shdr *ShdrBase; - -// -// PE section alignment. -// -const UINT32 CoffAlignment = 0x20; -const UINT32 CoffNbrSections = 4; - -// -// Current offset in coff file. -// -UINT32 CoffOffset; - -// -// Result Coff file in memory. -// -UINT8 *CoffFile; - -// -// Offset in Coff file of headers and sections. -// -UINT32 NtHdrOffset; -UINT32 TableOffset; -UINT32 TextOffset; -UINT32 DataOffset; -UINT32 RelocOffset; - -// -// ELF sections to offset in Coff file. -// -UINT32 *CoffSectionsOffset; - -EFI_IMAGE_BASE_RELOCATION *CoffBaseRel; -UINT16 *CoffEntryRel; - -UINT32 -CoffAlign( - UINT32 Offset - ) -{ - return (Offset + CoffAlignment - 1) & ~(CoffAlignment - 1); -} - -Elf_Shdr * -GetShdrByIndex( - UINT32 Num - ) -{ - if (Num >= Ehdr->e_shnum) - return NULL; - return (Elf_Shdr*)((UINT8*)ShdrBase + Num * Ehdr->e_shentsize); -} - -INTN -CheckElfHeader( - VOID - ) -{
- // - // Note: Magic has already been tested. - // - if (Ehdr->e_ident[EI_CLASS] != ELFCLASS) - return 0; - if (Ehdr->e_ident[EI_DATA] != ELFDATA2LSB) - return 0; - if (Ehdr->e_type != ET_EXEC) - return 0; - if (Ehdr->e_machine != EM_386) - return 0; - if (Ehdr->e_version != EV_CURRENT) - return 0; -
- //
- // Find the section header table
- // - ShdrBase = (Elf_Shdr *)((UINT8 *)Ehdr + Ehdr->e_shoff); - - CoffSectionsOffset = (UINT32 *)malloc(Ehdr->e_shnum * sizeof (UINT32));
- - memset(CoffSectionsOffset, 0, Ehdr->e_shnum * sizeof(UINT32));
- return 1; -} - -int -IsTextShdr( - Elf_Shdr *Shdr - ) -{ - return (Shdr->sh_flags & (SHF_WRITE | SHF_ALLOC)) == SHF_ALLOC; -} -
-int -IsDataShdr( - Elf_Shdr *Shdr - ) -{ - return (Shdr->sh_flags & (SHF_WRITE | SHF_ALLOC)) == (SHF_ALLOC | SHF_WRITE); -} - -void -CreateSectionHeader( - const char *Name, - UINT32 Offset, - UINT32 Size, - UINT32 Flags - ) -{ - EFI_IMAGE_SECTION_HEADER *Hdr; - Hdr = (EFI_IMAGE_SECTION_HEADER*)(CoffFile + TableOffset); - - strcpy(Hdr->Name, Name); - Hdr->Misc.VirtualSize = Size; - Hdr->VirtualAddress = Offset; - Hdr->SizeOfRawData = Size; - Hdr->PointerToRawData = Offset; - Hdr->PointerToRelocations = 0; - Hdr->PointerToLinenumbers = 0; - Hdr->NumberOfRelocations = 0; - Hdr->NumberOfLinenumbers = 0; - Hdr->Characteristics = Flags; - - TableOffset += sizeof (EFI_IMAGE_SECTION_HEADER); -} - -void -ScanSections( - VOID - ) -{ - UINT32 i; - EFI_IMAGE_DOS_HEADER *DosHdr; - EFI_IMAGE_NT_HEADERS *NtHdr; - UINT32 CoffEntry = 0; - - CoffOffset = 0; - - // - // Coff file start with a DOS header. - // - CoffOffset = sizeof(EFI_IMAGE_DOS_HEADER) + 0x40; - NtHdrOffset = CoffOffset; - CoffOffset += sizeof(EFI_IMAGE_NT_HEADERS); - TableOffset = CoffOffset; - CoffOffset += CoffNbrSections * sizeof(EFI_IMAGE_SECTION_HEADER); - - // - // First text sections. - // - CoffOffset = CoffAlign(CoffOffset); - TextOffset = CoffOffset; - for (i = 0; i < Ehdr->e_shnum; i++) { - Elf_Shdr *shdr = GetShdrByIndex(i); - if (IsTextShdr(shdr)) {
- //
- // Align the coff offset to meet with the alignment requirement of section
- // itself.
- //
- if ((shdr->sh_addralign != 0) && (shdr->sh_addralign != 1)) {
- CoffOffset = (CoffOffset + shdr->sh_addralign - 1) & ~(shdr->sh_addralign - 1);
- }
-
- /* Relocate entry. */ - if ((Ehdr->e_entry >= shdr->sh_addr) &&
- (Ehdr->e_entry < shdr->sh_addr + shdr->sh_size)) { - CoffEntry = CoffOffset + Ehdr->e_entry - shdr->sh_addr; - } - CoffSectionsOffset[i] = CoffOffset;
- CoffOffset += shdr->sh_size; - }
- }
- CoffOffset = CoffAlign(CoffOffset); -
- // - // Then data sections. - // - DataOffset = CoffOffset; - for (i = 0; i < Ehdr->e_shnum; i++) { - Elf_Shdr *shdr = GetShdrByIndex(i); - if (IsDataShdr(shdr)) {
- //
- // Align the coff offset to meet with the alignment requirement of section
- // itself.
- //
- if ((shdr->sh_addralign != 0) && (shdr->sh_addralign != 1)) {
- CoffOffset = (CoffOffset + shdr->sh_addralign - 1) & ~(shdr->sh_addralign - 1);
- } -
- CoffSectionsOffset[i] = CoffOffset; - CoffOffset += shdr->sh_size; - } - } - CoffOffset = CoffAlign(CoffOffset); - - RelocOffset = CoffOffset; - - // - // Allocate base Coff file. Will be expanded later for relocations. - // - CoffFile = (UINT8 *)malloc(CoffOffset); - memset(CoffFile, 0, CoffOffset); - - // - // Fill headers. - // - DosHdr = (EFI_IMAGE_DOS_HEADER *)CoffFile; - DosHdr->e_magic = EFI_IMAGE_DOS_SIGNATURE; - DosHdr->e_lfanew = NtHdrOffset; - - NtHdr = (EFI_IMAGE_NT_HEADERS*)(CoffFile + NtHdrOffset); - - NtHdr->Signature = EFI_IMAGE_NT_SIGNATURE; - - NtHdr->FileHeader.Machine = EFI_IMAGE_MACHINE_IA32; - NtHdr->FileHeader.NumberOfSections = CoffNbrSections; - NtHdr->FileHeader.TimeDateStamp = time(NULL); - NtHdr->FileHeader.PointerToSymbolTable = 0; - NtHdr->FileHeader.NumberOfSymbols = 0; - NtHdr->FileHeader.SizeOfOptionalHeader = sizeof(NtHdr->OptionalHeader); - NtHdr->FileHeader.Characteristics = EFI_IMAGE_FILE_EXECUTABLE_IMAGE - | EFI_IMAGE_FILE_LINE_NUMS_STRIPPED - | EFI_IMAGE_FILE_LOCAL_SYMS_STRIPPED - | EFI_IMAGE_FILE_32BIT_MACHINE; - - NtHdr->OptionalHeader.Magic = EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC; - NtHdr->OptionalHeader.SizeOfCode = DataOffset - TextOffset; - NtHdr->OptionalHeader.SizeOfInitializedData = RelocOffset - DataOffset; - NtHdr->OptionalHeader.SizeOfUninitializedData = 0; - NtHdr->OptionalHeader.AddressOfEntryPoint = CoffEntry; - NtHdr->OptionalHeader.BaseOfCode = TextOffset; - - NtHdr->OptionalHeader.BaseOfData = DataOffset; - NtHdr->OptionalHeader.ImageBase = 0; - NtHdr->OptionalHeader.SectionAlignment = CoffAlignment; - NtHdr->OptionalHeader.FileAlignment = CoffAlignment; - NtHdr->OptionalHeader.SizeOfImage = 0; - - NtHdr->OptionalHeader.SizeOfHeaders = TextOffset; - NtHdr->OptionalHeader.NumberOfRvaAndSizes = EFI_IMAGE_NUMBER_OF_DIRECTORY_ENTRIES; - - // - // Section headers. - // - CreateSectionHeader (".text", TextOffset, DataOffset - TextOffset, - EFI_IMAGE_SCN_CNT_CODE - | EFI_IMAGE_SCN_MEM_EXECUTE - | EFI_IMAGE_SCN_MEM_READ); - CreateSectionHeader (".data", DataOffset, RelocOffset - DataOffset, - EFI_IMAGE_SCN_CNT_INITIALIZED_DATA - | EFI_IMAGE_SCN_MEM_WRITE - | EFI_IMAGE_SCN_MEM_READ); -} - -void -WriteSections( - int (*Filter)(Elf_Shdr *) - ) -{ - UINT32 Idx; - - // - // First: copy sections. - // - for (Idx = 0; Idx < Ehdr->e_shnum; Idx++) { - Elf_Shdr *Shdr = GetShdrByIndex(Idx); - if ((*Filter)(Shdr)) { - switch (Shdr->sh_type) { - case SHT_PROGBITS: - /* Copy. */ - memcpy(CoffFile + CoffSectionsOffset[Idx], - (UINT8*)Ehdr + Shdr->sh_offset, - Shdr->sh_size); - break; - case SHT_NOBITS: - memset(CoffFile + CoffSectionsOffset[Idx], 0, Shdr->sh_size); - break; - default: - Error (NULL, 0, 0, InImageName, "unhandle section type %x", - (UINTN)Shdr->sh_type); - } - } - } - - // - // Second: apply relocations. - // - for (Idx = 0; Idx < Ehdr->e_shnum; Idx++) { - Elf_Shdr *RelShdr = GetShdrByIndex(Idx); - if (RelShdr->sh_type != SHT_REL) - continue; - Elf_Shdr *SecShdr = GetShdrByIndex(RelShdr->sh_info); - UINT32 SecOffset = CoffSectionsOffset[RelShdr->sh_info]; - if (RelShdr->sh_type == SHT_REL && (*Filter)(SecShdr)) { - UINT32 RelIdx; - Elf_Shdr *SymtabShdr = GetShdrByIndex(RelShdr->sh_link); - UINT8 *Symtab = (UINT8*)Ehdr + SymtabShdr->sh_offset; - - for (RelIdx = 0; RelIdx < RelShdr->sh_size; RelIdx += RelShdr->sh_entsize) { - Elf_Rel *Rel = (Elf_Rel *)((UINT8*)Ehdr + RelShdr->sh_offset + RelIdx); - Elf_Sym *Sym = (Elf_Sym *) - (Symtab + ELF_R_SYM(Rel->r_info) * SymtabShdr->sh_entsize); - Elf_Shdr *SymShdr; - UINT8 *Targ; - - if (Sym->st_shndx == SHN_UNDEF - || Sym->st_shndx == SHN_ABS - || Sym->st_shndx > Ehdr->e_shnum) { - Error (NULL, 0, 0, InImageName, "bad symbol definition"); - } - SymShdr = GetShdrByIndex(Sym->st_shndx); - - // - // Note: r_offset in a memory address. - // Convert it to a pointer in the coff file. - // - Targ = CoffFile + SecOffset + (Rel->r_offset - SecShdr->sh_addr); - - switch (ELF_R_TYPE(Rel->r_info)) { - case R_386_NONE: - break; - case R_386_32: - // - // Absolute relocation. - // - *(UINT32 *)Targ = *(UINT32 *)Targ - SymShdr->sh_addr - + CoffSectionsOffset[Sym->st_shndx]; - break; - case R_386_PC32: - // - // Relative relocation: Symbol - Ip + Addend - // - *(UINT32 *)Targ = *(UINT32 *)Targ - + (CoffSectionsOffset[Sym->st_shndx] - SymShdr->sh_addr) - - (SecOffset - SecShdr->sh_addr); - break; - default: - Error (NULL, 0, 0, InImageName, "unhandled relocation type %x", - ELF_R_TYPE(Rel->r_info)); - } - } - } - } -} - -void -CoffAddFixupEntry( - UINT16 Val - ) -{ - *CoffEntryRel = Val; - CoffEntryRel++; - CoffBaseRel->SizeOfBlock += 2; - CoffOffset += 2; -} - -void -CoffAddFixup( - UINT32 Offset, - UINT8 Type - ) -{ - if (CoffBaseRel == NULL - || CoffBaseRel->VirtualAddress != (Offset & ~0xfff)) { - if (CoffBaseRel != NULL) { - // - // Add a null entry (is it required ?) - // - CoffAddFixupEntry (0); - // - // Pad for alignment. - // - if (CoffOffset % 4 != 0) - CoffAddFixupEntry (0); - } - - CoffFile = realloc - (CoffFile, - CoffOffset + sizeof(EFI_IMAGE_BASE_RELOCATION) + 2*0x1000); - memset(CoffFile + CoffOffset, 0, - sizeof(EFI_IMAGE_BASE_RELOCATION) + 2*0x1000); - - CoffBaseRel = (EFI_IMAGE_BASE_RELOCATION*)(CoffFile + CoffOffset); - CoffBaseRel->VirtualAddress = Offset & ~0xfff; - CoffBaseRel->SizeOfBlock = sizeof(EFI_IMAGE_BASE_RELOCATION); - - CoffEntryRel = (UINT16 *)(CoffBaseRel + 1); - CoffOffset += sizeof(EFI_IMAGE_BASE_RELOCATION); - } - - // - // Fill the entry. - // - CoffAddFixupEntry((Type << 12) | (Offset & 0xfff)); -} - -void -WriteRelocations( - VOID - ) -{ - UINT32 Idx; - EFI_IMAGE_NT_HEADERS *NtHdr; - EFI_IMAGE_DATA_DIRECTORY *Dir; - - for (Idx = 0; Idx < Ehdr->e_shnum; Idx++) { - Elf_Shdr *RelShdr = GetShdrByIndex(Idx); - if (RelShdr->sh_type == SHT_REL) { - Elf_Shdr *SecShdr = GetShdrByIndex(RelShdr->sh_info); - if (IsTextShdr(SecShdr) || IsDataShdr(SecShdr)) { - UINT32 RelIdx; - for (RelIdx = 0; RelIdx < RelShdr->sh_size; RelIdx += RelShdr->sh_entsize) { - Elf_Rel *Rel = (Elf_Rel *) - ((UINT8*)Ehdr + RelShdr->sh_offset + RelIdx); - switch (ELF_R_TYPE(Rel->r_info)) { - case R_386_NONE: - case R_386_PC32: - break; - case R_386_32: - CoffAddFixup(CoffSectionsOffset[RelShdr->sh_info] - + (Rel->r_offset - SecShdr->sh_addr), - EFI_IMAGE_REL_BASED_HIGHLOW); - break; - default: - Error (NULL, 0, 0, InImageName, "unhandled relocation type %x", - ELF_R_TYPE(Rel->r_info)); - } - } - } - } - } - - // - // Pad by adding empty entries. - // - while (CoffOffset & (CoffAlignment - 1)) { - CoffAddFixupEntry(0); - } - - CreateSectionHeader (".reloc", RelocOffset, CoffOffset - RelocOffset, - EFI_IMAGE_SCN_CNT_INITIALIZED_DATA - | EFI_IMAGE_SCN_MEM_DISCARDABLE - | EFI_IMAGE_SCN_MEM_READ); - - NtHdr = (EFI_IMAGE_NT_HEADERS *)(CoffFile + NtHdrOffset); - Dir = &NtHdr->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC]; - Dir->VirtualAddress = RelocOffset; - Dir->Size = CoffOffset - RelocOffset; -} - -void -WriteDebug( - VOID - ) -{ - UINT32 Len = strlen(InImageName) + 1; - UINT32 DebugOffset = CoffOffset; - EFI_IMAGE_NT_HEADERS *NtHdr; - EFI_IMAGE_DATA_DIRECTORY *DataDir; - EFI_IMAGE_DEBUG_DIRECTORY_ENTRY *Dir; - EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY *Nb10; - - CoffOffset += sizeof(EFI_IMAGE_DEBUG_DIRECTORY_ENTRY) - + sizeof(EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY) - + Len; - CoffOffset = CoffAlign(CoffOffset); - - CoffFile = realloc - (CoffFile, CoffOffset); - memset(CoffFile + DebugOffset, 0, CoffOffset - DebugOffset); - - Dir = (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY*)(CoffFile + DebugOffset); - Dir->Type = EFI_IMAGE_DEBUG_TYPE_CODEVIEW; - Dir->SizeOfData = sizeof(EFI_IMAGE_DEBUG_DIRECTORY_ENTRY) + Len; - Dir->RVA = DebugOffset + sizeof(EFI_IMAGE_DEBUG_DIRECTORY_ENTRY); - Dir->FileOffset = DebugOffset + sizeof(EFI_IMAGE_DEBUG_DIRECTORY_ENTRY); - - Nb10 = (EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY*)(Dir + 1); - Nb10->Signature = CODEVIEW_SIGNATURE_NB10; - strcpy ((PUCHAR)(Nb10 + 1), InImageName); - - CreateSectionHeader (".debug", DebugOffset, CoffOffset - DebugOffset, - EFI_IMAGE_SCN_CNT_INITIALIZED_DATA - | EFI_IMAGE_SCN_MEM_DISCARDABLE - | EFI_IMAGE_SCN_MEM_READ); - - NtHdr = (EFI_IMAGE_NT_HEADERS *)(CoffFile + NtHdrOffset); - DataDir = &NtHdr->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG]; - DataDir->VirtualAddress = DebugOffset; - DataDir->Size = CoffOffset - DebugOffset; -} - -void -ConvertElf ( - UINT8 **FileBuffer, - UINTN *FileLength - ) -{ - EFI_IMAGE_NT_HEADERS *NtHdr; - - // - // Check header, read section table. - // - Ehdr = (Elf32_Ehdr*)*FileBuffer; - if (!CheckElfHeader()) - return; - - // - // Compute sections new address. - // - ScanSections(); - - // - // Write and relocate sections. - // - WriteSections(IsTextShdr); - WriteSections(IsDataShdr); - - // - // Translate and write relocations. - // - WriteRelocations(); - - // - // Write debug info. - // - WriteDebug(); - - NtHdr = (EFI_IMAGE_NT_HEADERS *)(CoffFile + NtHdrOffset); - NtHdr->OptionalHeader.SizeOfImage = CoffOffset; - - // - // Replace. - // - free(*FileBuffer); - *FileBuffer = CoffFile; - *FileLength = CoffOffset; -} -#endif // HAVE_ELF - -int
-main (
- int argc,
- char *argv[]
- )
-/*++
-
-Routine Description:
-
- Main function.
-
-Arguments:
-
- argc - Number of command line parameters.
- argv - Array of pointers to command line parameter strings.
-
-Returns:
- STATUS_SUCCESS - Utility exits successfully.
- STATUS_ERROR - Some error occurred during execution.
-
---*/
-{
- ULONG Type;
- PUCHAR Ext;
- PUCHAR p;
- PUCHAR pe;
- PUCHAR OutImageName;
- UCHAR outname[500];
- FILE *fpIn;
- FILE *fpOut;
- 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;
- ULONG Index2;
- ULONG Index3;
- BOOLEAN TimeStampPresent;
- UINTN AllignedRelocSize;
- UINTN Delta;
- EFI_IMAGE_SECTION_HEADER *SectionHeader;
- UINT8 *FileBuffer;
- UINTN FileLength;
- RUNTIME_FUNCTION *RuntimeFunction;
- UNWIND_INFO *UnwindInfo;
-
- SetUtilityName (UTILITY_NAME);
- //
- // Assign to fix compile warning
- //
- OutImageName = NULL;
- Type = 0;
- Ext = 0;
- TimeStamp = 0;
- TimeStampPresent = FALSE;
-
- if (argc == 1) {
- Usage();
- return STATUS_ERROR;
- }
-
- if ((strcmp(argv[1], "-h") == 0) || (strcmp(argv[1], "--help") == 0) ||
- (strcmp(argv[1], "-?") == 0) || (strcmp(argv[1], "/?") == 0)) {
- Usage();
- return STATUS_ERROR;
- }
-
- if ((strcmp(argv[1], "-V") == 0) || (strcmp(argv[1], "--version") == 0)) {
- Version();
- return STATUS_ERROR;
- }
-
- //
- // Look for -t time-date option first. If the time is "0", then
- // skip it.
- //
- if ((argc > 2) && !strcmp (argv[1], "-t")) {
- TimeStampPresent = TRUE;
- if (strcmp (argv[2], "0") != 0) {
- //
- // Convert the string to a value
- //
- memset ((char *) &TimeStruct, 0, sizeof (TimeStruct));
- if (sscanf(
- argv[2], "%d/%d/%d,%d:%d:%d",
- &TimeStruct.tm_mon, /* months since January - [0,11] */
- &TimeStruct.tm_mday, /* day of the month - [1,31] */
- &TimeStruct.tm_year, /* years since 1900 */
- &TimeStruct.tm_hour, /* hours since midnight - [0,23] */
- &TimeStruct.tm_min, /* minutes after the hour - [0,59] */
- &TimeStruct.tm_sec /* seconds after the minute - [0,59] */
- ) != 6) {
- Error (NULL, 0, 0, argv[2], "failed to convert to mm/dd/yyyy,hh:mm:ss format");
- return STATUS_ERROR;
- }
- //
- // Now fixup some of the fields
- //
- TimeStruct.tm_mon--;
- TimeStruct.tm_year -= 1900;
- //
- // Sanity-check values?
- // Convert
- //
- TimeStamp = mktime (&TimeStruct);
- if (TimeStamp == (time_t) - 1) {
- Error (NULL, 0, 0, argv[2], "failed to convert time");
- return STATUS_ERROR;
- }
- }
- //
- // Skip over the args
- //
- argc -= 2;
- argv += 2;
- }
- //
- // Check for enough args
- //
- if (argc < 3) {
- Usage ();
- return STATUS_ERROR;
- }
-
- InImageName = argv[2];
-
- if (argc == 4) {
- OutImageName = argv[3];
- }
- //
- // Get new image type
- //
- p = argv[1];
- if (*p == '/' || *p == '\\') {
- p += 1;
- }
-
- 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, "DXE_DRIVER") == 0) {
- Type = EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER;
- Ext = ".efi";
-
- } 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, "DXE_SAL_DRIVER") == 0) {
- Type = EFI_IMAGE_SUBSYSTEM_SAL_RUNTIME_DRIVER;
- Ext = ".efi";
- } 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, "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;
- }
- //
- // open source file
- //
- fpIn = fopen (InImageName, "rb");
- if (!fpIn) {
- Error (NULL, 0, 0, InImageName, "failed to open input file for reading");
- return STATUS_ERROR;
- }
-
- FReadFile (fpIn, (VOID **)&FileBuffer, &FileLength);
-
-#ifdef HAVE_ELF - if (IsElfHeader(FileBuffer)) { - ConvertElf(&FileBuffer, &FileLength); - } -#endif - //
- // Read the dos & pe hdrs of the image
- //
- DosHdr = (EFI_IMAGE_DOS_HEADER *)FileBuffer;
- if (DosHdr->e_magic != EFI_IMAGE_DOS_SIGNATURE) {
- Error (NULL, 0, 0, InImageName, "DOS header signature not found in source image");
- fclose (fpIn);
- return STATUS_ERROR;
- }
-
- PeHdr = (EFI_IMAGE_NT_HEADERS *)(FileBuffer + DosHdr->e_lfanew);
- if (PeHdr->Signature != EFI_IMAGE_NT_SIGNATURE) {
- Error (NULL, 0, 0, InImageName, "PE header signature not found in source image");
- fclose (fpIn);
- return STATUS_ERROR;
- }
-
- //
- // open output file
- //
- strcpy (outname, InImageName);
- pe = NULL;
- for (p = outname; *p; p++) {
- if (*p == '.') {
- pe = p;
- }
- }
-
- if (!pe) {
- pe = p;
- }
-
- strcpy (pe, Ext);
-
- if (!OutImageName) {
- OutImageName = outname;
- }
-
- fpOut = fopen (OutImageName, "w+b");
- if (!fpOut) {
- Error (NULL, 0, 0, OutImageName, "could not open output file for writing");
- fclose (fpIn);
- return STATUS_ERROR;
- }
-
- //
- // Zero all unused fields of the DOS header
- //
- 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;
- }
-
- //
- // Patch the PE header
- //
- PeHdr->OptionalHeader.Subsystem = (USHORT) Type;
- if (TimeStampPresent) {
- 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;
-
- //
- // 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) {
- RuntimeFunction = (RUNTIME_FUNCTION *)(FileBuffer + SectionHeader->PointerToRawData);
- for (Index1 = 0; Index1 < Optional64->DataDirectory[3].Size / sizeof (RUNTIME_FUNCTION); Index1++, RuntimeFunction++) {
- SectionHeader = (EFI_IMAGE_SECTION_HEADER *)(FileBuffer + DosHdr->e_lfanew + sizeof(UINT32) + sizeof (EFI_IMAGE_FILE_HEADER) + PeHdr->FileHeader.SizeOfOptionalHeader);
- for (Index2 = 0; Index2 < PeHdr->FileHeader.NumberOfSections; Index2++, SectionHeader++) {
- if (RuntimeFunction->UnwindInfoAddress > SectionHeader->VirtualAddress && RuntimeFunction->UnwindInfoAddress < (SectionHeader->VirtualAddress + SectionHeader->SizeOfRawData)) {
- UnwindInfo = (UNWIND_INFO *)(FileBuffer + SectionHeader->PointerToRawData + (RuntimeFunction->UnwindInfoAddress - SectionHeader->VirtualAddress));
- if (UnwindInfo->Version == 1) {
- memset (UnwindInfo + 1, 0, UnwindInfo->CountOfUnwindCodes * sizeof (UINT16));
- memset (UnwindInfo, 0, sizeof (UNWIND_INFO));
- }
- }
- }
- memset (RuntimeFunction, 0, sizeof (RUNTIME_FUNCTION));
- }
-
- break;
- }
- }
- 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;
- }
- }
- }
- }
- }
- }
- }
-
- FWriteFile (fpOut, FileBuffer, FileLength);
-
- //
- // Done
- //
- fclose (fpIn);
- fclose (fpOut);
- //
- // printf ("Created %s\n", OutImageName);
- //
- return STATUS_SUCCESS;
-}
|