13eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang/*++
23eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
33e99020dbf0a159e34b84e7ae9125f2e368d5390lgaoCopyright (c) 2004 - 2010, Intel Corporation. All rights reserved.<BR>
44b1e11214a01fa6994e3f77c2481f2723a32221bhhtianThis program and the accompanying materials
53eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwangare licensed and made available under the terms and conditions of the BSD License
63eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwangwhich accompanies this distribution.  The full text of the license may be found at
73eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwanghttp://opensource.org/licenses/bsd-license.php
83eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
93eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwangTHE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
103eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwangWITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
113eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
123eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwangModule Name:
133eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
143eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  fwimage.c
153eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
163eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwangAbstract:
173eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
183eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  Converts a pe32/pe32+ image to an FW image type
193eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
203eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang--*/
213eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
223eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang#include <windows.h>
233eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang#include <stdio.h>
243eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang#include <stdlib.h>
253eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang#include <string.h>
263eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang#include <time.h>
273eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
283eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang#include "TianoCommon.h"
293eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang#include "EfiImage.h"
303eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang#include "EfiUtilityMsgs.c"
313eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
323e99020dbf0a159e34b84e7ae9125f2e368d5390lgao#define UTILITY_NAME    "FwImage"
333e99020dbf0a159e34b84e7ae9125f2e368d5390lgao#define UTILITY_VERSION "v1.0"
343eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
353eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwangtypedef union {
363eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  IMAGE_NT_HEADERS32 PeHeader32;
373eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  IMAGE_NT_HEADERS64 PeHeader64;
383eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang} PE_HEADER;
393eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
403eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwangVOID
413eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwangUsage (
423eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  VOID
433eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  )
443eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang{
453e99020dbf0a159e34b84e7ae9125f2e368d5390lgao  int         Index;
463e99020dbf0a159e34b84e7ae9125f2e368d5390lgao  const char  *Str[] = {
473e99020dbf0a159e34b84e7ae9125f2e368d5390lgao    UTILITY_NAME" "UTILITY_VERSION" - Intel Firmware Image Utility",
483e99020dbf0a159e34b84e7ae9125f2e368d5390lgao    "  Copyright (C), 2004 - 2008 Intel Corporation",
493e99020dbf0a159e34b84e7ae9125f2e368d5390lgao
503e99020dbf0a159e34b84e7ae9125f2e368d5390lgao#if ( defined(UTILITY_BUILD) && defined(UTILITY_VENDOR) )
513e99020dbf0a159e34b84e7ae9125f2e368d5390lgao    "  Built from "UTILITY_BUILD", project of "UTILITY_VENDOR,
523e99020dbf0a159e34b84e7ae9125f2e368d5390lgao#endif
533e99020dbf0a159e34b84e7ae9125f2e368d5390lgao
543e99020dbf0a159e34b84e7ae9125f2e368d5390lgao    "",
553e99020dbf0a159e34b84e7ae9125f2e368d5390lgao    "Usage:",
563e99020dbf0a159e34b84e7ae9125f2e368d5390lgao    "  "UTILITY_NAME" [OPTION]... FWTYPE SOURCE [DEST]",
573e99020dbf0a159e34b84e7ae9125f2e368d5390lgao    "Description:",
583e99020dbf0a159e34b84e7ae9125f2e368d5390lgao    "  Converts a pe32/pe32+ SOURCE to DEST with FWTYPE image type.",
593e99020dbf0a159e34b84e7ae9125f2e368d5390lgao    "Options:",
603e99020dbf0a159e34b84e7ae9125f2e368d5390lgao    "  FWTYPE        Can be one of APPLICATION, BS_DRIVER, RT_DRIVER, SAL_RT_DRIVER,",
613e99020dbf0a159e34b84e7ae9125f2e368d5390lgao    "                COMBINED_PEIM_DRIVER, SECURITY_CORE, PEI_CORE, PE32_PEIM and",
623e99020dbf0a159e34b84e7ae9125f2e368d5390lgao    "                RELOCATABLE_PEIM",
633e99020dbf0a159e34b84e7ae9125f2e368d5390lgao    "  -t time-date  Add Time Stamp for output image",
643e99020dbf0a159e34b84e7ae9125f2e368d5390lgao    "  -e            Not clear ExceptionTable for output image",
653e99020dbf0a159e34b84e7ae9125f2e368d5390lgao    "  -r            Not strip zero pending of .reloc for output image",
663e99020dbf0a159e34b84e7ae9125f2e368d5390lgao    NULL
673e99020dbf0a159e34b84e7ae9125f2e368d5390lgao  };
683e99020dbf0a159e34b84e7ae9125f2e368d5390lgao
693e99020dbf0a159e34b84e7ae9125f2e368d5390lgao  for (Index = 0; Str[Index] != NULL; Index++) {
703e99020dbf0a159e34b84e7ae9125f2e368d5390lgao    fprintf (stdout, "%s\n", Str[Index]);
713e99020dbf0a159e34b84e7ae9125f2e368d5390lgao  }
723eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang}
733eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
743eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwangstatic
753eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwangSTATUS
763eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwangFReadFile (
773eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  FILE    *in,
783eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  VOID    **Buffer,
793eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  UINTN   *Length
803eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  )
813eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang{
823eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  fseek (in, 0, SEEK_END);
833eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  *Length = ftell (in);
843eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  *Buffer = malloc (*Length);
853eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  fseek (in, 0, SEEK_SET);
863eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  fread (*Buffer, *Length, 1, in);
873eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  return STATUS_SUCCESS;
883eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang}
893eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
903eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwangstatic
913eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwangSTATUS
923eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwangFWriteFile (
933eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  FILE    *out,
943eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  VOID    *Buffer,
953eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  UINTN   Length
963eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  )
973eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang{
983eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  fseek (out, 0, SEEK_SET);
993eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  fwrite (Buffer, Length, 1, out);
1003eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  if ((ULONG) ftell (out) != Length) {
1013eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang    Error (NULL, 0, 0, "write error", NULL);
1023eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang    return STATUS_ERROR;
1033eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  }
1043eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  free (Buffer);
1053eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  return STATUS_SUCCESS;
1063eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang}
1073eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
1083eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwangVOID
1093eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwangZeroExceptionTable (
1103eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  IN UINT8                 *FileBuffer,
1113eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  IN EFI_IMAGE_DOS_HEADER  *DosHdr,
1123eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  IN PE_HEADER             *PeHdr
1133eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  )
1143eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang{
1153eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  UINT32                   PdataSize;
1163eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  UINT32                   PdataOffset;
1173eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  UINT32                   PdataRVASize;
1183eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  UINT32                   PdataRVA;
1193eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  UINT32                   SectionOffset;
1203eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  UINT16                   SectionNumber;
1213eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  UINT32                   SectionNameSize;
1223eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  EFI_IMAGE_SECTION_HEADER *Section;
1233eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
1243eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  PdataSize     = 0;
1253eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  PdataOffset   = 0;
1263eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  PdataRVASize  = 0;
1273eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  PdataRVA      = 0;
1283eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  SectionOffset = 0;
1293eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
1303eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  //
1313eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  // Search .pdata section
1323eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  //
1333eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  if (PeHdr->PeHeader32.OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
1343eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang    if ((PeHdr->PeHeader32.OptionalHeader.NumberOfRvaAndSizes > IMAGE_DIRECTORY_ENTRY_EXCEPTION) &&
1353eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang        (PeHdr->PeHeader32.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXCEPTION].VirtualAddress != 0) &&
1363eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang        (PeHdr->PeHeader32.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXCEPTION].Size != 0)) {
1373eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
1383eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang      PdataRVA     = PeHdr->PeHeader32.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXCEPTION].VirtualAddress;
1393eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang      PdataRVASize = PeHdr->PeHeader32.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXCEPTION].Size;
1403eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
1413eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang      PeHdr->PeHeader32.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXCEPTION].VirtualAddress = 0;
1423eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang      PeHdr->PeHeader32.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXCEPTION].Size = 0;
1433eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
1443eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang      SectionOffset = sizeof(PeHdr->PeHeader32);
1453eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang    }
1463eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  } else {
1473eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang    if ((PeHdr->PeHeader64.OptionalHeader.NumberOfRvaAndSizes > IMAGE_DIRECTORY_ENTRY_EXCEPTION) &&
1483eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang        (PeHdr->PeHeader64.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXCEPTION].VirtualAddress != 0) &&
1493eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang        (PeHdr->PeHeader64.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXCEPTION].Size != 0)) {
1503eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
1513eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang      PdataRVA     = PeHdr->PeHeader64.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXCEPTION].VirtualAddress;
1523eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang      PdataRVASize = PeHdr->PeHeader64.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXCEPTION].Size;
1533eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
1543eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang      PeHdr->PeHeader64.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXCEPTION].VirtualAddress = 0;
1553eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang      PeHdr->PeHeader64.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXCEPTION].Size = 0;
1563eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
1573eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang      SectionOffset = sizeof(PeHdr->PeHeader64);
1583eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang    }
1593eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  }
1603eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
1613eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  if ((PdataRVASize != 0) && (PdataRVA != 0)) {
1623eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
1633eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang    SectionNumber = PeHdr->PeHeader32.FileHeader.NumberOfSections;
1643eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang    SectionNameSize = sizeof(Section->Name);
1653eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang    while (SectionNumber > 0) {
1663eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang      Section = (EFI_IMAGE_SECTION_HEADER *) &FileBuffer[DosHdr->e_lfanew + SectionOffset];
1673eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang      if (strcmp (Section->Name, ".pdata") == 0) {
1683eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang        //
1693eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang        // Zero .pdata Section Header Name
1703eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang        //
1713eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang        memset (
1723eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang          FileBuffer + DosHdr->e_lfanew + SectionOffset,
1733eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang          0,
1743eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang          SectionNameSize);
1753eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
1763eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang        //
1773eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang        // Zero .pdata Secton raw data
1783eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang        //
1793eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang        PdataOffset = Section->PointerToRawData;
1803eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang        PdataSize   = Section->SizeOfRawData;
1813eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang        memset (FileBuffer + PdataOffset, 0, PdataSize);
1823eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang        break;
1833eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang      }
1843eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang      SectionNumber--;
1853eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang      SectionOffset += sizeof(EFI_IMAGE_SECTION_HEADER);
1863eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang    }
1873eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  }
1883eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
1893eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  return ;
1903eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang}
1913eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
1923eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwangVOID
1933eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwangStripZeroPendingReloc (
1943eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  IN UINT8                 *FileBuffer,
1953eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  IN OUT UINTN             *FileLength,
1963eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  IN EFI_IMAGE_DOS_HEADER  *DosHdr,
1973eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  IN PE_HEADER             *PeHdr
1983eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  )
1993eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang{
2003eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  EFI_IMAGE_OPTIONAL_HEADER32  *Optional32;
2013eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  EFI_IMAGE_OPTIONAL_HEADER64  *Optional64;
2023eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  EFI_IMAGE_SECTION_HEADER     *SectionHeader;
2033eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  UINTN                        AllignedRelocSize;
2043eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  UINTN                        Index;
2053eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
2063eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  if (PeHdr->PeHeader32.OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
2073eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang    Optional32 = (EFI_IMAGE_OPTIONAL_HEADER32 *)&PeHdr->PeHeader32.OptionalHeader;
2083eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang    if ((Optional32->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC) &&
2093eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang        (Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size != 0)) {
2103eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang      SectionHeader = (EFI_IMAGE_SECTION_HEADER *)(FileBuffer + DosHdr->e_lfanew + sizeof(UINT32) + sizeof (EFI_IMAGE_FILE_HEADER) + PeHdr->PeHeader32.FileHeader.SizeOfOptionalHeader);
2113eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang      for (Index = 0; Index < PeHdr->PeHeader32.FileHeader.NumberOfSections; Index++, SectionHeader++) {
2123eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang        //
2133eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang        // Look for the Section Header that starts as the same virtual address as the Base Relocation Data Directory
2143eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang        //
2153eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang        if (strcmp (SectionHeader->Name, ".reloc") == 0) {
2163eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang          SectionHeader->Misc.VirtualSize = Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size;
2173eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
2183eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang          AllignedRelocSize = (Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size +
2193eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang                               Optional32->FileAlignment - 1) & (~(Optional32->FileAlignment - 1));
2203eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang          //
2213eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang          // Check to see if there is zero padding at the end of the base relocations
2223eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang          //
2233eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang          if (AllignedRelocSize < SectionHeader->SizeOfRawData) {
2243eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang            //
2253eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang            // Check to see if the base relocations are at the end of the file
2263eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang            //
2273eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang            if (SectionHeader->PointerToRawData + SectionHeader->SizeOfRawData == Optional32->SizeOfImage) {
2283eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang              //
2293eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang              // All the required conditions are met to strip the zero padding of the end of the base relocations section
2303eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang              //
2313eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang              Optional32->SizeOfImage           -= (SectionHeader->SizeOfRawData - AllignedRelocSize);
2323eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang              Optional32->SizeOfInitializedData -= (SectionHeader->SizeOfRawData - AllignedRelocSize);
2333eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang              SectionHeader->SizeOfRawData       = AllignedRelocSize;
2343eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang              *FileLength                        = Optional32->SizeOfImage;
2353eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang            }
2363eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang          }
2373eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang        }
2383eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang      }
2393eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang    }
2403eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  } else {
2413eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang    Optional64 = (EFI_IMAGE_OPTIONAL_HEADER64 *)&PeHdr->PeHeader64.OptionalHeader;
2423eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang    if ((Optional64->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC) &&
2433eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang        (Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size != 0)) {
2443eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang      SectionHeader = (EFI_IMAGE_SECTION_HEADER *)(FileBuffer + DosHdr->e_lfanew + sizeof(UINT32) + sizeof (EFI_IMAGE_FILE_HEADER) + PeHdr->PeHeader64.FileHeader.SizeOfOptionalHeader);
2453eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang      for (Index = 0; Index < PeHdr->PeHeader64.FileHeader.NumberOfSections; Index++, SectionHeader++) {
2463eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang        //
2473eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang        // Look for the Section Header that starts as the same virtual address as the Base Relocation Data Directory
2483eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang        //
2493eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang        if (strcmp (SectionHeader->Name, ".reloc") == 0) {
2503eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang          SectionHeader->Misc.VirtualSize = Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size;
2513eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
2523eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang          AllignedRelocSize = (Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size +
2533eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang                               Optional64->FileAlignment - 1) & (~(Optional64->FileAlignment - 1));
2543eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang          //
2553eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang          // Check to see if there is zero padding at the end of the base relocations
2563eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang          //
2573eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang          if (AllignedRelocSize < SectionHeader->SizeOfRawData) {
2583eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang            //
2593eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang            // Check to see if the base relocations are at the end of the file
2603eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang            //
2613eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang            if (SectionHeader->PointerToRawData + SectionHeader->SizeOfRawData == Optional64->SizeOfImage) {
2623eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang              //
2633eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang              // All the required conditions are met to strip the zero padding of the end of the base relocations section
2643eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang              //
2653eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang              Optional64->SizeOfImage           -= (SectionHeader->SizeOfRawData - AllignedRelocSize);
2663eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang              Optional64->SizeOfInitializedData -= (SectionHeader->SizeOfRawData - AllignedRelocSize);
2673eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang              SectionHeader->SizeOfRawData       = AllignedRelocSize;
2683eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang              *FileLength                        = Optional64->SizeOfImage;
2693eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang            }
2703eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang          }
2713eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang        }
2723eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang      }
2733eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang    }
2743eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  }
2753eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang}
2763eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
2773eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwangint
2783eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwangmain (
2793eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  int  argc,
2803eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  char *argv[]
2813eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  )
2823eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang/*++
2833eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
2843eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwangRoutine Description:
2853eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
2863eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  Main function.
2873eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
2883eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwangArguments:
2893eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
2903eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  argc - Number of command line parameters.
2913eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  argv - Array of pointers to command line parameter strings.
2923eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
2933eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwangReturns:
2943eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
2953eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  STATUS_SUCCESS - Utility exits successfully.
2963eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  STATUS_ERROR   - Some error occurred during execution.
2973eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
2983eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang--*/
2993eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang{
3003eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  ULONG                        Type;
3013eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  PUCHAR                       Ext;
3023eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  PUCHAR                       p;
3033eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  PUCHAR                       pe;
3043eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  PUCHAR                       OutImageName;
3053eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  UCHAR                        outname[500];
3063eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  FILE                         *fpIn;
3073eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  FILE                         *fpOut;
3083eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  EFI_IMAGE_DOS_HEADER         *DosHdr;
3093eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  PE_HEADER                    *PeHdr;
3103eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  time_t                       TimeStamp;
3113eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  struct tm                    TimeStruct;
3123eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  EFI_IMAGE_DOS_HEADER         BackupDosHdr;
3133eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  ULONG                        Index;
3143eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  BOOLEAN                      TimeStampPresent;
3153eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  BOOLEAN                      NeedClearExceptionTable;
3163eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  BOOLEAN                      NeedStripZeroPendingReloc;
3173eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  UINT8                        *FileBuffer;
3183eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  UINTN                        FileLength;
3193eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  EFI_IMAGE_OPTIONAL_HEADER32  *Optional32;
3203eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  EFI_IMAGE_OPTIONAL_HEADER64  *Optional64;
3213eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
3223eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  SetUtilityName (UTILITY_NAME);
3233eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  //
3243eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  // Assign to fix compile warning
3253eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  //
3263eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  OutImageName      = NULL;
3273eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  Type              = 0;
3283eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  Ext               = 0;
3293eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  TimeStamp         = 0;
3303eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  TimeStampPresent  = FALSE;
3313eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
3323eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  NeedClearExceptionTable   = TRUE;
3333eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  NeedStripZeroPendingReloc = TRUE;
3343eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
3353eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  //
3363eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  // Look for -t time-date option first. If the time is "0", then
3373eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  // skip it.
3383eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  //
3393eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  if ((argc > 2) && !strcmp (argv[1], "-t")) {
3403eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang    TimeStampPresent = TRUE;
3413eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang    if (strcmp (argv[2], "0") != 0) {
3423eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang      //
3433eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang      // Convert the string to a value
3443eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang      //
3453eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang      memset ((char *) &TimeStruct, 0, sizeof (TimeStruct));
3463eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang      if (sscanf(
3473eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang          argv[2], "%d/%d/%d,%d:%d:%d",
3483eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang          &TimeStruct.tm_mon,   /* months since January - [0,11] */
3493eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang          &TimeStruct.tm_mday,  /* day of the month - [1,31] */
3503eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang          &TimeStruct.tm_year,  /* years since 1900 */
3513eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang          &TimeStruct.tm_hour,  /* hours since midnight - [0,23] */
3523eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang          &TimeStruct.tm_min,   /* minutes after the hour - [0,59] */
3533eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang          &TimeStruct.tm_sec    /* seconds after the minute - [0,59] */
3543eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang            ) != 6) {
3553eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang        Error (NULL, 0, 0, argv[2], "failed to convert to mm/dd/yyyy,hh:mm:ss format");
3563eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang        return STATUS_ERROR;
3573eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang      }
3583eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang      //
3593eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang      // Now fixup some of the fields
3603eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang      //
3613eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang      TimeStruct.tm_mon--;
3623eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang      TimeStruct.tm_year -= 1900;
3633eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang      //
3643eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang      // Sanity-check values?
3653eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang      // Convert
3663eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang      //
3673eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang      TimeStamp = mktime (&TimeStruct);
3683eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang      if (TimeStamp == (time_t) - 1) {
3693eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang        Error (NULL, 0, 0, argv[2], "failed to convert time");
3703eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang        return STATUS_ERROR;
3713eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang      }
3723eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang    }
3733eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang    //
3743eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang    // Skip over the args
3753eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang    //
3763eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang    argc -= 2;
3773eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang    argv += 2;
3783eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  }
3793eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
3803eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  //
3813eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  // Look for -e option.
3823eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  //
3833eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  if ((argc > 1) && !strcmp (argv[1], "-e")) {
3843eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang    NeedClearExceptionTable = FALSE;
3853eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang    //
3863eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang    // Skip over the args
3873eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang    //
3883eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang    argc -= 1;
3893eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang    argv += 1;
3903eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  }
3913eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
3923eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  //
3933eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  // Look for -r option
3943eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  //
3953eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  if ((argc > 1) && !strcmp (argv[1], "-r")) {
3963eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang    NeedStripZeroPendingReloc = FALSE;
3973eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang    //
3983eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang    // Skip over the args
3993eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang    //
4003eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang    argc -= 1;
4013eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang    argv += 1;
4023eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  }
4033eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
4043eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  //
4053eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  // Check for enough args
4063eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  //
4073eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  if (argc < 3) {
4083eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang    Usage ();
4093eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang    return STATUS_ERROR;
4103eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  }
4113eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
4123eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  if (argc == 4) {
4133eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang    OutImageName = argv[3];
4143eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  }
4153eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  //
4163eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  // Get new image type
4173eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  //
4183eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  p = argv[1];
4193eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  if (*p == '/' || *p == '\\') {
4203eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang    p += 1;
4213eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  }
4223eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
4233eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  if (_stricmp (p, "app") == 0 || _stricmp (p, "APPLICATION") == 0) {
4243eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang    Type  = EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION;
4253eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang    Ext   = ".efi";
4263eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
4273eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  } else if (_stricmp (p, "bsdrv") == 0 || _stricmp (p, "BS_DRIVER") == 0) {
4283eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang    Type  = EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER;
4293eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang    Ext   = ".efi";
4303eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
4313eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  } else if (_stricmp (p, "rtdrv") == 0 || _stricmp (p, "RT_DRIVER") == 0) {
4323eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang    Type  = EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER;
4333eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang    Ext   = ".efi";
4343eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
4353eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  } else if (_stricmp (p, "rtdrv") == 0 || _stricmp (p, "SAL_RT_DRIVER") == 0) {
4363eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang    Type  = EFI_IMAGE_SUBSYSTEM_SAL_RUNTIME_DRIVER;
4373eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang    Ext   = ".efi";
4383eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  } else if (_stricmp (p, "SECURITY_CORE") == 0) {
4393eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang    Type  = EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER;
4403eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang    Ext   = ".sec";
4413eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  } else if (_stricmp (p, "peim") == 0 ||
4423eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang           _stricmp (p, "PEI_CORE") == 0 ||
4433eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang           _stricmp (p, "PE32_PEIM") == 0 ||
4443eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang           _stricmp (p, "RELOCATABLE_PEIM") == 0 ||
4453eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang           _stricmp (p, "combined_peim_driver") == 0
4463eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang          ) {
4473eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang    Type  = EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER;
4483eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang    Ext   = ".pei";
4493eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  } else {
4503eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang    Usage ();
4513eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang    return STATUS_ERROR;
4523eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  }
4533eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  //
4543eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  // open source file
4553eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  //
4563eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  fpIn = fopen (argv[2], "rb");
4573eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  if (!fpIn) {
4583eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang    Error (NULL, 0, 0, argv[2], "failed to open input file for reading");
4593eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang    return STATUS_ERROR;
4603eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  }
4613eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  FReadFile (fpIn, (VOID **)&FileBuffer, &FileLength);
4623eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  //
4633eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  // Read the dos & pe hdrs of the image
4643eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  //
4653eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  DosHdr = (EFI_IMAGE_DOS_HEADER *) FileBuffer;
4663eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  if (DosHdr->e_magic != IMAGE_DOS_SIGNATURE) {
4673eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang    Error (NULL, 0, 0, argv[2], "DOS header signature not found in source image");
4683eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang    fclose (fpIn);
4693eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang    return STATUS_ERROR;
4703eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  }
4713eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
4723eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  PeHdr = (PE_HEADER *)(FileBuffer + DosHdr->e_lfanew);
4733eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  if (PeHdr->PeHeader32.Signature != IMAGE_NT_SIGNATURE) {
4743eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang    Error (NULL, 0, 0, argv[2], "PE header signature not found in source image");
4753eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang    fclose (fpIn);
4763eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang    return STATUS_ERROR;
4773eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  }
4783eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  //
4793eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  // open output file
4803eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  //
4813eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  strcpy (outname, argv[2]);
4823eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  pe = NULL;
4833eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  for (p = outname; *p; p++) {
4843eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang    if (*p == '.') {
4853eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang      pe = p;
4863eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang    }
4873eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  }
4883eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
4893eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  if (!pe) {
4903eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang    pe = p;
4913eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  }
4923eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
4933eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  strcpy (pe, Ext);
4943eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
4953eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  if (!OutImageName) {
4963eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang    OutImageName = outname;
4973eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  }
4983eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
4993eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  fpOut = fopen (OutImageName, "w+b");
5003eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  if (!fpOut) {
5013eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang    Error (NULL, 0, 0, OutImageName, "could not open output file for writing");
5023eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang    fclose (fpIn);
5033eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang    return STATUS_ERROR;
5043eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  }
5053eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  //
5063eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  // Zero all unused fields of the DOS header
5073eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  //
5083eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  memcpy (&BackupDosHdr, DosHdr, sizeof (EFI_IMAGE_DOS_HEADER));
5093eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  memset (DosHdr, 0, sizeof (EFI_IMAGE_DOS_HEADER));
5103eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  DosHdr->e_magic  = BackupDosHdr.e_magic;
5113eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  DosHdr->e_lfanew = BackupDosHdr.e_lfanew;
5123eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
5133eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  for (Index = sizeof (EFI_IMAGE_DOS_HEADER); Index < (ULONG) DosHdr->e_lfanew; Index++) {
5143eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang    FileBuffer[Index] = (UINT8) DosHdr->e_cp;
5153eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  }
5163eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
5173eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  //
5183eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  // Modify some fields in the PE header
5193eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  //
5203eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
5213eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  //
5223eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  // TimeDateStamp's offset is fixed for PE32/32+
5233eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  //
5243eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  if (TimeStampPresent) {
5253eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang    PeHdr->PeHeader32.FileHeader.TimeDateStamp = (UINT32) TimeStamp;
5263eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  }
5273eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
5283eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  //
5293eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  // PE32/32+ has different optional header layout
5303eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  // Determine format is PE32 or PE32+ before modification
5313eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  //
5323eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  if (PeHdr->PeHeader32.OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
5333eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang    //
5343eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang    // PE32 image
5353eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang    //
5363eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang    Optional32 = (EFI_IMAGE_OPTIONAL_HEADER32 *)&PeHdr->PeHeader32.OptionalHeader;
5373eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
5383eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang    Optional32->MajorLinkerVersion          = 0;
5393eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang    Optional32->MinorLinkerVersion          = 0;
5403eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang    Optional32->MajorOperatingSystemVersion = 0;
5413eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang    Optional32->MinorOperatingSystemVersion = 0;
5423eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang    Optional32->MajorImageVersion           = 0;
5433eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang    Optional32->MinorImageVersion           = 0;
5443eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang    Optional32->MajorSubsystemVersion       = 0;
5453eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang    Optional32->MinorSubsystemVersion       = 0;
5463eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang    Optional32->Win32VersionValue           = 0;
5473eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang    Optional32->CheckSum                    = 0;
5483eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang    Optional32->SizeOfStackReserve          = 0;
5493eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang    Optional32->SizeOfStackCommit           = 0;
5503eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang    Optional32->SizeOfHeapReserve           = 0;
5513eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang    Optional32->SizeOfHeapCommit            = 0;
5523eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang    Optional32->Subsystem                   = (USHORT) Type;
5533eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
5543eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang    //
5553eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang    // Strip zero padding at the end of the .reloc section
5563eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang    //
5573eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang    if (NeedStripZeroPendingReloc) {
5583eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang      StripZeroPendingReloc (FileBuffer, &FileLength, DosHdr, PeHdr);
5593eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang    }
5603eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  } else if (PeHdr->PeHeader32.OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR64_MAGIC) {
5613eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang    //
5623eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang    // PE32+ image
5633eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang    //
5643eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang    Optional64 = (EFI_IMAGE_OPTIONAL_HEADER64 *)&PeHdr->PeHeader64.OptionalHeader;
5653eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
5663eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang    Optional64->MajorLinkerVersion          = 0;
5673eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang    Optional64->MinorLinkerVersion          = 0;
5683eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang    Optional64->MajorOperatingSystemVersion = 0;
5693eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang    Optional64->MinorOperatingSystemVersion = 0;
5703eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang    Optional64->MajorImageVersion           = 0;
5713eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang    Optional64->MinorImageVersion           = 0;
5723eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang    Optional64->MajorSubsystemVersion       = 0;
5733eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang    Optional64->MinorSubsystemVersion       = 0;
5743eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang    Optional64->Win32VersionValue           = 0;
5753eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang    Optional64->CheckSum                    = 0;
5763eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang    Optional64->SizeOfStackReserve          = 0;
5773eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang    Optional64->SizeOfStackCommit           = 0;
5783eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang    Optional64->SizeOfHeapReserve           = 0;
5793eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang    Optional64->SizeOfHeapCommit            = 0;
5803eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang    Optional64->Subsystem                   = (USHORT) Type;
5813eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
5823eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang    //
5833eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang    // Strip zero padding at the end of the .reloc section
5843eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang    //
5853eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang    if (NeedStripZeroPendingReloc) {
5863eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang      StripZeroPendingReloc (FileBuffer, &FileLength, DosHdr, PeHdr);
5873eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang    }
5883eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  } else {
5893eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang    Error (NULL, 0, 0, argv[2], "Unsupported PE image");
5903eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang    fclose (fpIn);
5913eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang    fclose (fpOut);
5923eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang    return STATUS_ERROR;
5933eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  }
5943eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
5953eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  //
5963eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  // Zero PDATA section for smaller binary size after compression
5973eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  //
5983eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  if (NeedClearExceptionTable) {
5993eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang    ZeroExceptionTable (FileBuffer, DosHdr, PeHdr);
6003eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  }
6013eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
6023eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  FWriteFile (fpOut, FileBuffer, FileLength);
6033eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
6043eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  //
6053eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  // Done
6063eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  //
6073eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  fclose (fpIn);
6083eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  fclose (fpOut);
6093eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang
6103eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang  return STATUS_SUCCESS;
6113eb9473ea9a949badfe06ae61d2d3fcfa53651c7qwang}
612