]> git.proxmox.com Git - mirror_edk2.git/blobdiff - BaseTools/Source/C/GenFw/GenFw.c
Sync EDKII BaseTools to BaseTools project r1903.
[mirror_edk2.git] / BaseTools / Source / C / GenFw / GenFw.c
index aabd143b6a1f6891866c18c1bdf264a6b5326435..d42c88e23d9f193baef5e6b7d3871b4d8406016b 100644 (file)
@@ -1,6 +1,6 @@
 /** @file\r
 \r
-Copyright (c) 2004 - 2009, Intel Corporation\r
+Copyright (c) 2004 - 2010, 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
@@ -78,6 +78,8 @@ Abstract:
 #define FW_RELOC_STRIPEED_IMAGE 9\r
 #define FW_HII_PACKAGE_LIST_RCIMAGE 10\r
 #define FW_HII_PACKAGE_LIST_BINIMAGE 11\r
+#define FW_REBASE_IMAGE      12\r
+#define FW_SET_ADDRESS_IMAGE 13\r
 \r
 #define DUMP_TE_HEADER       0x11\r
 \r
@@ -116,6 +118,12 @@ static const char *gHiiPackageRCFileHeader[] = {
 \r
 STATIC CHAR8 *mInImageName;\r
 \r
+//\r
+// Module image information\r
+//\r
+STATIC UINT32 mImageTimeStamp = 0;\r
+STATIC UINT32 mImageSize = 0;\r
+\r
 STATIC\r
 EFI_STATUS\r
 ZeroDebugData (\r
@@ -190,7 +198,7 @@ Returns:
   //\r
   // Copyright declaration\r
   //\r
-  fprintf (stdout, "Copyright (c) 2007, Intel Corporation. All rights reserved.\n\n");\r
+  fprintf (stdout, "Copyright (c) 2007 - 2010, Intel Corporation. All rights reserved.\n\n");\r
 \r
   //\r
   // Details Option\r
@@ -244,7 +252,9 @@ Returns:
   fprintf (stdout, "  -s timedate, --stamp timedate\n\\r
                         timedate format is \"yyyy-mm-dd 00:00:00\". if timedata \n\\r
                         is set to NOW, current system time is used. The support\n\\r
-                        date scope is 1970-1-1 8:0:0 ~ 2038-1-19 3:14:07\n\\r
+                        date scope is 1970-01-01 00+timezone:00:00\n\\r
+                        ~ 2038-01-19 03+timezone:14:07\n\\r
+                        The scope is adjusted according to the different zones.\n\\r
                         It can't be combined with other action options\n\\r
                         except for -o, -r option. It is a action option.\n\\r
                         If it is combined with other action options, the later\n\\r
@@ -288,6 +298,18 @@ Returns:
                         except for -o option. It is a action option.\n\\r
                         If it is combined with other action options, the later\n\\r
                         input action option will override the previous one.\n");\r
+  fprintf (stdout, "  --rebase NewAddress   Rebase image to new base address. New address \n\\r
+                        is also set to the first none code section header.\n\\r
+                        It can't be combined with other action options\n\\r
+                        except for -o or -r option. It is a action option.\n\\r
+                        If it is combined with other action options, the later\n\\r
+                        input action option will override the previous one.\n");\r
+  fprintf (stdout, "  --address NewAddress  Set new address into the first none code \n\\r
+                        section header of the input image.\n\\r
+                        It can't be combined with other action options\n\\r
+                        except for -o or -r option. It is a action option.\n\\r
+                        If it is combined with other action options, the later\n\\r
+                        input action option will override the previous one.\n");\r
   fprintf (stdout, "  -v, --verbose         Turn on verbose output with informational messages.\n");\r
   fprintf (stdout, "  -q, --quiet           Disable all messages except key message and fatal error\n");\r
   fprintf (stdout, "  -d, --debug level     Enable debug messages, at input debug level.\n");\r
@@ -860,6 +882,7 @@ ScanSections(
 \r
   NtHdr->Pe32.FileHeader.NumberOfSections = CoffNbrSections;\r
   NtHdr->Pe32.FileHeader.TimeDateStamp = (UINT32) time(NULL);\r
+  mImageTimeStamp = NtHdr->Pe32.FileHeader.TimeDateStamp;\r
   NtHdr->Pe32.FileHeader.PointerToSymbolTable = 0;\r
   NtHdr->Pe32.FileHeader.NumberOfSymbols = 0;\r
   NtHdr->Pe32.FileHeader.SizeOfOptionalHeader = sizeof(NtHdr->Pe32.OptionalHeader);\r
@@ -1639,6 +1662,257 @@ Returns:
   return HiiSectionHeader;\r
 }\r
 \r
+EFI_STATUS\r
+RebaseImageRead (\r
+  IN     VOID    *FileHandle,\r
+  IN     UINTN   FileOffset,\r
+  IN OUT UINT32  *ReadSize,\r
+  OUT    VOID    *Buffer\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Support routine for the PE/COFF Loader that reads a buffer from a PE/COFF file\r
+\r
+Arguments:\r
+\r
+  FileHandle - The handle to the PE/COFF file\r
+\r
+  FileOffset - The offset, in bytes, into the file to read\r
+\r
+  ReadSize   - The number of bytes to read from the file starting at FileOffset\r
+\r
+  Buffer     - A pointer to the buffer to read the data into.\r
+\r
+Returns:\r
+\r
+  EFI_SUCCESS - ReadSize bytes of data were read into Buffer from the PE/COFF file starting at FileOffset\r
+\r
+--*/\r
+{\r
+  CHAR8   *Destination8;\r
+  CHAR8   *Source8;\r
+  UINT32  Length;\r
+\r
+  Destination8  = Buffer;\r
+  Source8       = (CHAR8 *) ((UINTN) FileHandle + FileOffset);\r
+  Length        = *ReadSize;\r
+  while (Length--) {\r
+    *(Destination8++) = *(Source8++);\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+SetAddressToSectionHeader (\r
+  IN     CHAR8   *FileName,\r
+  IN OUT UINT8   *FileBuffer,\r
+  IN     UINT64  NewPe32BaseAddress\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Set new base address into the section header of PeImage\r
+\r
+Arguments:\r
+\r
+  FileName           - Name of file\r
+  FileBuffer         - Pointer to PeImage.\r
+  NewPe32BaseAddress - New Base Address for PE image.\r
+\r
+Returns:\r
+\r
+  EFI_SUCCESS          Set new base address into this image successfully.\r
+\r
+--*/\r
+{\r
+  EFI_STATUS                            Status;\r
+  PE_COFF_LOADER_IMAGE_CONTEXT          ImageContext;\r
+  UINTN                                 Index;\r
+  EFI_IMAGE_OPTIONAL_HEADER_UNION       *ImgHdr;\r
+  EFI_IMAGE_SECTION_HEADER              *SectionHeader;\r
+\r
+  //\r
+  // Initialize context\r
+  //\r
+  memset (&ImageContext, 0, sizeof (ImageContext));\r
+  ImageContext.Handle     = (VOID *) FileBuffer;\r
+  ImageContext.ImageRead  = (PE_COFF_LOADER_READ_FILE) RebaseImageRead;\r
+  Status                  = PeCoffLoaderGetImageInfo (&ImageContext);\r
+  if (EFI_ERROR (Status)) {\r
+    Error (NULL, 0, 3000, "Invalid", "The input PeImage %s is not valid", FileName);\r
+    return Status;\r
+  }\r
+\r
+  if (ImageContext.RelocationsStripped) {\r
+    Error (NULL, 0, 3000, "Invalid", "The input PeImage %s has no relocation to be fixed up", FileName);\r
+    return Status;    \r
+  }\r
+\r
+  //\r
+  // Get PeHeader pointer\r
+  //\r
+  ImgHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION *)(FileBuffer + ImageContext.PeCoffHeaderOffset);\r
+\r
+  //\r
+  // Get section header list\r
+  //\r
+  SectionHeader = (EFI_IMAGE_SECTION_HEADER *) (\r
+    (UINTN) ImgHdr +\r
+    sizeof (UINT32) + \r
+    sizeof (EFI_IMAGE_FILE_HEADER) +  \r
+    ImgHdr->Pe32.FileHeader.SizeOfOptionalHeader\r
+    );\r
+\r
+  //\r
+  // Set base address into the first section header that doesn't point to code section.\r
+  //\r
+  for (Index = 0; Index < ImgHdr->Pe32.FileHeader.NumberOfSections; Index ++, SectionHeader ++) {\r
+    if ((SectionHeader->Characteristics & EFI_IMAGE_SCN_CNT_CODE) == 0) {\r
+      *(UINT64 *) &SectionHeader->PointerToRelocations = NewPe32BaseAddress;\r
+      break;\r
+    }\r
+  }\r
+\r
+  //\r
+  // No available section header is found.\r
+  //\r
+  if (Index == ImgHdr->Pe32.FileHeader.NumberOfSections) {\r
+    return EFI_NOT_FOUND;\r
+  }\r
+  \r
+  //\r
+  // BaseAddress is set to section header.\r
+  //\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+RebaseImage (\r
+  IN     CHAR8   *FileName,\r
+  IN OUT UINT8   *FileBuffer,\r
+  IN     UINT64  NewPe32BaseAddress\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Set new base address into PeImage, and fix up PeImage based on new address.\r
+\r
+Arguments:\r
+\r
+  FileName           - Name of file\r
+  FileBuffer         - Pointer to PeImage.\r
+  NewPe32BaseAddress - New Base Address for PE image.\r
+\r
+Returns:\r
+\r
+  EFI_INVALID_PARAMETER   - BaseAddress is not valid.\r
+  EFI_SUCCESS             - Update PeImage is correctly.\r
+\r
+--*/\r
+{\r
+  EFI_STATUS                            Status;\r
+  PE_COFF_LOADER_IMAGE_CONTEXT          ImageContext;\r
+  UINTN                                 Index;\r
+  EFI_IMAGE_OPTIONAL_HEADER_UNION       *ImgHdr;\r
+  UINT8                                 *MemoryImagePointer;\r
+  EFI_IMAGE_SECTION_HEADER              *SectionHeader;\r
+\r
+  //\r
+  // Initialize context\r
+  //\r
+  memset (&ImageContext, 0, sizeof (ImageContext));\r
+  ImageContext.Handle     = (VOID *) FileBuffer;\r
+  ImageContext.ImageRead  = (PE_COFF_LOADER_READ_FILE) RebaseImageRead;\r
+  Status                  = PeCoffLoaderGetImageInfo (&ImageContext);\r
+  if (EFI_ERROR (Status)) {\r
+    Error (NULL, 0, 3000, "Invalid", "The input PeImage %s is not valid", FileName);\r
+    return Status;\r
+  }\r
+\r
+  if (ImageContext.RelocationsStripped) {\r
+    Error (NULL, 0, 3000, "Invalid", "The input PeImage %s has no relocation to be fixed up", FileName);\r
+    return Status;    \r
+  }\r
+\r
+  //\r
+  // Get PeHeader pointer\r
+  //\r
+  ImgHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION *)(FileBuffer + ImageContext.PeCoffHeaderOffset);\r
+\r
+  //\r
+  // Load and Relocate Image Data\r
+  //\r
+  MemoryImagePointer = (UINT8 *) malloc ((UINTN) ImageContext.ImageSize + ImageContext.SectionAlignment);\r
+  if (MemoryImagePointer == NULL) {\r
+    Error (NULL, 0, 4001, "Resource", "memory cannot be allocated on rebase of %s", FileName);\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+  memset ((VOID *) MemoryImagePointer, 0, (UINTN) ImageContext.ImageSize + ImageContext.SectionAlignment);\r
+  ImageContext.ImageAddress = ((UINTN) MemoryImagePointer + ImageContext.SectionAlignment - 1) & (~((INT64)ImageContext.SectionAlignment - 1));\r
+\r
+  Status =  PeCoffLoaderLoadImage (&ImageContext);\r
+  if (EFI_ERROR (Status)) {\r
+    Error (NULL, 0, 3000, "Invalid", "LocateImage() call failed on rebase of %s", FileName);\r
+    free ((VOID *) MemoryImagePointer);\r
+    return Status;\r
+  }\r
+\r
+  ImageContext.DestinationAddress = NewPe32BaseAddress;\r
+  Status                          = PeCoffLoaderRelocateImage (&ImageContext);\r
+  if (EFI_ERROR (Status)) {\r
+    Error (NULL, 0, 3000, "Invalid", "RelocateImage() call failed on rebase of %s", FileName);\r
+    free ((VOID *) MemoryImagePointer);\r
+    return Status;\r
+  }\r
+\r
+  //\r
+  // Copy Relocated data to raw image file.\r
+  //\r
+  SectionHeader = (EFI_IMAGE_SECTION_HEADER *) (\r
+    (UINTN) ImgHdr +\r
+    sizeof (UINT32) + \r
+    sizeof (EFI_IMAGE_FILE_HEADER) +  \r
+    ImgHdr->Pe32.FileHeader.SizeOfOptionalHeader\r
+    );\r
+\r
+  for (Index = 0; Index < ImgHdr->Pe32.FileHeader.NumberOfSections; Index ++, SectionHeader ++) {\r
+    CopyMem (\r
+      FileBuffer + SectionHeader->PointerToRawData, \r
+      (VOID*) (UINTN) (ImageContext.ImageAddress + SectionHeader->VirtualAddress), \r
+      SectionHeader->SizeOfRawData\r
+      );\r
+  }\r
+\r
+  free ((VOID *) MemoryImagePointer);\r
+\r
+  //\r
+  // Update Image Base Address\r
+  //\r
+  if ((ImgHdr->Pe32.OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) && (ImgHdr->Pe32.FileHeader.Machine != IMAGE_FILE_MACHINE_IA64)) {\r
+    ImgHdr->Pe32.OptionalHeader.ImageBase = (UINT32) NewPe32BaseAddress;\r
+  } else if (ImgHdr->Pe32Plus.OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC) {\r
+    ImgHdr->Pe32Plus.OptionalHeader.ImageBase = NewPe32BaseAddress;\r
+  } else {\r
+    Error (NULL, 0, 3000, "Invalid", "unknown PE magic signature %X in PE32 image %s",\r
+      ImgHdr->Pe32.OptionalHeader.Magic,\r
+      FileName\r
+      );\r
+    return EFI_ABORTED;\r
+  }\r
+\r
+  //\r
+  // Set new base address into section header\r
+  //\r
+  Status = SetAddressToSectionHeader (FileName, FileBuffer, NewPe32BaseAddress);\r
+\r
+  return Status;\r
+}\r
+\r
 int\r
 main (\r
   int  argc,\r
@@ -1686,6 +1960,8 @@ Returns:
   UINT32                           FileLength;\r
   UINT8                            *OutputFileBuffer;\r
   UINT32                           OutputFileLength;\r
+  UINT8                            *InputFileBuffer;\r
+  UINT32                           InputFileLength;\r
   RUNTIME_FUNCTION                 *RuntimeFunction;\r
   UNWIND_INFO                      *UnwindInfo;\r
   STATUS                           Status;\r
@@ -1712,12 +1988,18 @@ Returns:
   EFI_HII_PACKAGE_HEADER           EndPackage;\r
   UINT32                           HiiSectionHeaderSize;\r
   UINT8                            *HiiSectionHeader;\r
+  UINT64                           NewBaseAddress;\r
+  BOOLEAN                          NegativeAddr;\r
+  FILE                             *ReportFile;\r
+  CHAR8                            *ReportFileName;\r
+  UINTN                            FileLen;\r
 \r
   SetUtilityName (UTILITY_NAME);\r
 \r
   //\r
   // Assign to fix compile warning\r
   //\r
+  FileLen           = 0;\r
   InputFileNum      = 0;\r
   InputFileName     = NULL;\r
   mInImageName      = NULL;\r
@@ -1740,6 +2022,8 @@ Returns:
   LogLevel          = 0;\r
   OutputFileBuffer  = NULL;\r
   OutputFileLength  = 0;\r
+  InputFileBuffer   = NULL;\r
+  InputFileLength   = 0;\r
   Optional32        = NULL;\r
   Optional64        = NULL;\r
   KeepExceptionTableFlag = FALSE;\r
@@ -1752,6 +2036,8 @@ Returns:
   memset (&HiiPackageListGuid, 0, sizeof (HiiPackageListGuid));\r
   HiiSectionHeaderSize   = 0;\r
   HiiSectionHeader       = NULL;\r
+  NewBaseAddress         = 0;\r
+  NegativeAddr           = FALSE;\r
 \r
   if (argc == 1) {\r
     Error (NULL, 0, 1001, "Missing options", "No input options.");\r
@@ -1899,6 +2185,44 @@ Returns:
       continue;\r
     }\r
 \r
+    if ((stricmp (argv[0], "--rebase") == 0)) {\r
+      if (argv[1][0] == '-') {\r
+        NegativeAddr = TRUE;\r
+        Status = AsciiStringToUint64 (argv[1] + 1, FALSE, &Temp64);\r
+      } else {\r
+        NegativeAddr = FALSE;\r
+        Status = AsciiStringToUint64 (argv[1], FALSE, &Temp64);\r
+      }\r
+      if (Status != EFI_SUCCESS) {\r
+        Error (NULL, 0, 1003, "Invalid option value", "%s = %s", argv[0], argv[1]);\r
+        goto Finish;\r
+      }\r
+      OutImageType = FW_REBASE_IMAGE;\r
+      NewBaseAddress = (UINT64) Temp64;\r
+      argc -= 2;\r
+      argv += 2;\r
+      continue;\r
+    }\r
+\r
+    if ((stricmp (argv[0], "--address") == 0)) {\r
+      if (argv[1][0] == '-') {\r
+        NegativeAddr = TRUE;\r
+        Status = AsciiStringToUint64 (argv[1] + 1, FALSE, &Temp64);\r
+      } else {\r
+        NegativeAddr = FALSE;\r
+        Status = AsciiStringToUint64 (argv[1], FALSE, &Temp64);\r
+      }\r
+      if (Status != EFI_SUCCESS) {\r
+        Error (NULL, 0, 1003, "Invalid option value", "%s = %s", argv[0], argv[1]);\r
+        goto Finish;\r
+      }\r
+      OutImageType = FW_SET_ADDRESS_IMAGE;\r
+      NewBaseAddress = (UINT64) Temp64;\r
+      argc -= 2;\r
+      argv += 2;\r
+      continue;\r
+    }\r
+\r
     if ((stricmp (argv[0], "-p") == 0) || (stricmp (argv[0], "--pad") == 0)) {\r
       if (AsciiStringToUint64 (argv[1], FALSE, &Temp64) != EFI_SUCCESS) {\r
         Error (NULL, 0, 1003, "Invalid option value", "%s = %s", argv[0], argv[1]);\r
@@ -1942,7 +2266,7 @@ Returns:
       argv += 2;\r
       continue;\r
     }\r
-    \r
+\r
     if ((stricmp (argv[0], "-g") == 0) || (stricmp (argv[0], "--hiiguid") == 0)) {\r
       Status = StringToGuid (argv[1], &HiiPackageListGuid);\r
       if (EFI_ERROR (Status)) {\r
@@ -1988,9 +2312,9 @@ Returns:
       // InputFileName buffer too small, need to realloc\r
       //\r
       InputFileName = (CHAR8 **) realloc (\r
-                                  InputFileName,\r
-                                  (InputFileNum + MAXIMUM_INPUT_FILE_NUM) * sizeof (CHAR8 *)\r
-                                  );\r
+        InputFileName,\r
+        (InputFileNum + MAXIMUM_INPUT_FILE_NUM) * sizeof (CHAR8 *)\r
+        );\r
 \r
       if (InputFileName == NULL) {\r
         Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!");\r
@@ -2090,6 +2414,12 @@ Returns:
   case FW_HII_PACKAGE_LIST_BINIMAGE:\r
     VerboseMsg ("Combine the input multi hii bin packages to one binary pacakge list file.");\r
     break;\r
+  case FW_REBASE_IMAGE:\r
+    VerboseMsg ("Rebase the input image to new base address.");\r
+    break;\r
+  case FW_SET_ADDRESS_IMAGE:\r
+    VerboseMsg ("Set the preferred address into the section header of the input image");\r
+    break;\r
   default:\r
     break;\r
   }\r
@@ -2114,33 +2444,52 @@ Returns:
       }\r
       fread (OutputFileBuffer, 1, OutputFileLength, fpOut);\r
       fclose (fpOut);\r
-    }\r
-    fpOut = fopen (OutImageName, "wb");\r
-    if (!fpOut) {\r
-      Error (NULL, 0, 0001, "Error opening output file", OutImageName);\r
-      goto Finish;\r
+      fpOut = NULL;\r
     }\r
     VerboseMsg ("Output file name is %s", OutImageName);\r
-  } else if (!ReplaceFlag) {\r
-    if (OutImageType == DUMP_TE_HEADER) {\r
-      fpOut = stdout;\r
-    } else {\r
-      Error (NULL, 0, 1001, "Missing option", "output file");\r
-      goto Finish;\r
-    }\r
+  } else if (!ReplaceFlag && OutImageType != DUMP_TE_HEADER) {\r
+    Error (NULL, 0, 1001, "Missing option", "output file");\r
+    goto Finish;\r
   }\r
 \r
+  //\r
+  // Open input file and read file data into file buffer.\r
+  //\r
+  fpIn = fopen (mInImageName, "rb");\r
+  if (fpIn == NULL) {\r
+    Error (NULL, 0, 0001, "Error opening file", mInImageName);\r
+    goto Finish;\r
+  }\r
+  InputFileLength = _filelength (fileno (fpIn));\r
+  InputFileBuffer = malloc (InputFileLength);\r
+  if (InputFileBuffer == NULL) {\r
+    Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!");\r
+    fclose (fpIn);\r
+    goto Finish;\r
+  }\r
+  fread (InputFileBuffer, 1, InputFileLength, fpIn);\r
+  fclose (fpIn);\r
+  DebugMsg (NULL, 0, 9, "input file info", "the input file size is %u bytes", (unsigned) InputFileLength);\r
+\r
   //\r
   // Combine multi binary HII package files.\r
   //\r
   if (OutImageType == FW_HII_PACKAGE_LIST_RCIMAGE || OutImageType == FW_HII_PACKAGE_LIST_BINIMAGE) {\r
+    //\r
+    // Open output file handle.\r
+    //\r
+    fpOut = fopen (OutImageName, "wb");\r
+    if (!fpOut) {\r
+      Error (NULL, 0, 0001, "Error opening output file", OutImageName);\r
+      goto Finish;\r
+    }\r
     //\r
     // Get hii package list lenght\r
     //\r
     HiiPackageListHeader.PackageLength = sizeof (EFI_HII_PACKAGE_LIST_HEADER);\r
     for (Index = 0; Index < InputFileNum; Index ++) {\r
       fpIn = fopen (InputFileName [Index], "rb");\r
-      if (!fpIn) {\r
+      if (fpIn == NULL) {\r
         Error (NULL, 0, 0001, "Error opening file", InputFileName [Index]);\r
         goto Finish;\r
       }\r
@@ -2186,7 +2535,7 @@ Returns:
     HiiPackageDataPointer = HiiPackageListBuffer + sizeof (HiiPackageListHeader);\r
     for (Index = 0; Index < InputFileNum; Index ++) {\r
       fpIn = fopen (InputFileName [Index], "rb");\r
-      if (!fpIn) {\r
+      if (fpIn == NULL) {\r
         Error (NULL, 0, 0001, "Error opening file", InputFileName [Index]);\r
         free (HiiPackageListBuffer);\r
         goto Finish;\r
@@ -2240,7 +2589,7 @@ Returns:
         fprintf (fpOut, " 0x%04X,", *(UINT16 *) HiiPackageDataPointer);\r
         HiiPackageDataPointer += 2;\r
       }\r
-      \r
+\r
       if (Index % 16 == 0) {\r
         fprintf (fpOut, "\n ");\r
       }\r
@@ -2262,6 +2611,14 @@ Returns:
   // Combine MciBinary files to one file\r
   //\r
   if (OutImageType == FW_MERGE_IMAGE) {\r
+    //\r
+    // Open output file handle.\r
+    //\r
+    fpOut = fopen (OutImageName, "wb");\r
+    if (!fpOut) {\r
+      Error (NULL, 0, 0001, "Error opening output file", OutImageName);\r
+      goto Finish;\r
+    }\r
     for (Index = 0; Index < InputFileNum; Index ++) {\r
       fpIn = fopen (InputFileName [Index], "rb");\r
       if (!fpIn) {\r
@@ -2306,7 +2663,7 @@ Returns:
   //\r
   if (OutImageType == FW_MCI_IMAGE) {\r
     fpIn = fopen (mInImageName, "r");\r
-    if (!fpIn) {\r
+    if (fpIn == NULL) {\r
       Error (NULL, 0, 0001, "Error opening file", mInImageName);\r
       goto Finish;\r
     }\r
@@ -2400,63 +2757,21 @@ Returns:
     //\r
     // Open the output file and write the buffer contents\r
     //\r
-    if (fpOut != NULL) {\r
-      if (fwrite (FileBuffer, FileLength, 1, fpOut) != 1) {\r
-        Error (NULL, 0, 0002, "Error writing file", OutImageName);\r
-        goto Finish;\r
-      }\r
-    }\r
-\r
-    if (ReplaceFlag) {\r
-      fpInOut = fopen (mInImageName, "wb");\r
-      if (fpInOut != NULL) {\r
-        Error (NULL, 0, 0001, "Error opening file", mInImageName);\r
-        goto Finish;\r
-      }\r
-      if (fwrite (FileBuffer, FileLength, 1, fpInOut) != 1) {\r
-        Error (NULL, 0, 0002, "Error writing file", mInImageName);\r
-        goto Finish;\r
-      }\r
-    }\r
     VerboseMsg ("the size of output file is %u bytes", (unsigned) FileLength);\r
-    //\r
-    //  Convert Mci.TXT to Mci.bin file successfully\r
-    //\r
-    goto Finish;\r
+    goto WriteFile;\r
   }\r
 \r
   //\r
   // Open input file and read file data into file buffer.\r
   //\r
-  fpIn = fopen (mInImageName, "rb");\r
-  if (!fpIn) {\r
-    Error (NULL, 0, 0001, "Error opening file", mInImageName);\r
-    goto Finish;\r
-  }\r
-\r
-  FileLength = _filelength (fileno (fpIn));\r
+  FileLength = InputFileLength;\r
   FileBuffer = malloc (FileLength);\r
   if (FileBuffer == NULL) {\r
     Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!");\r
-    fclose (fpIn);\r
     goto Finish;\r
   }\r
+  memcpy (FileBuffer, InputFileBuffer, InputFileLength);\r
 \r
-  fread (FileBuffer, 1, FileLength, fpIn);\r
-  fclose (fpIn);\r
-\r
-  DebugMsg (NULL, 0, 9, "input file info", "the input file size is %u bytes", (unsigned) FileLength);\r
-\r
-  //\r
-  // Replace file\r
-  //\r
-  if (ReplaceFlag) {\r
-    fpInOut = fopen (mInImageName, "wb");\r
-    if (!fpInOut) {\r
-      Error (NULL, 0, 0001, "Error opening file", mInImageName);\r
-      goto Finish;\r
-    }\r
-  }\r
   //\r
   // Dump TeImage Header into output file.\r
   //\r
@@ -2466,6 +2781,26 @@ Returns:
       Error (NULL, 0, 3000, "Invalid", "TE header signature of file %s is not correct.", mInImageName);\r
       goto Finish;\r
     }\r
+    //\r
+    // Open the output file handle.\r
+    //\r
+    if (ReplaceFlag) {\r
+      fpInOut = fopen (mInImageName, "wb");\r
+      if (fpInOut == NULL) {\r
+        Error (NULL, 0, 0001, "Error opening file", mInImageName);\r
+        goto Finish;\r
+      }\r
+    } else {\r
+      if (OutImageName != NULL) {\r
+        fpOut = fopen (OutImageName, "wb");\r
+      } else {\r
+        fpOut = stdout;\r
+      }\r
+      if (fpOut == NULL) {\r
+        Error (NULL, 0, 0001, "Error opening output file", OutImageName);\r
+        goto Finish;\r
+      }\r
+    }\r
     if (fpInOut != NULL) {\r
       fprintf (fpInOut, "Dump of file %s\n\n", mInImageName);\r
       fprintf (fpInOut, "TE IMAGE HEADER VALUES\n");\r
@@ -2479,7 +2814,6 @@ Returns:
       fprintf (fpInOut, "%17X [%8X] RVA [size] of Base Relocation Directory\n", (unsigned) TEImageHeader.DataDirectory[0].VirtualAddress, (unsigned) TEImageHeader.DataDirectory[0].Size);\r
       fprintf (fpInOut, "%17X [%8X] RVA [size] of Debug Directory\n", (unsigned) TEImageHeader.DataDirectory[1].VirtualAddress, (unsigned) TEImageHeader.DataDirectory[1].Size);\r
     }\r
-\r
     if (fpOut != NULL) {\r
       fprintf (fpOut, "Dump of file %s\n\n", mInImageName);\r
       fprintf (fpOut, "TE IMAGE HEADER VALUES\n");\r
@@ -2514,36 +2848,36 @@ Returns:
       }\r
     } else {\r
       if (stricmp (ModuleType, "BASE") == 0 ||\r
-          stricmp (ModuleType, "SEC") == 0 ||\r
-          stricmp (ModuleType, "SECURITY_CORE") == 0 ||\r
-          stricmp (ModuleType, "PEI_CORE") == 0 ||\r
-          stricmp (ModuleType, "PEIM") == 0 ||\r
-          stricmp (ModuleType, "COMBINED_PEIM_DRIVER") == 0 ||\r
-          stricmp (ModuleType, "PIC_PEIM") == 0 ||\r
-          stricmp (ModuleType, "RELOCATABLE_PEIM") == 0 ||\r
-          stricmp (ModuleType, "DXE_CORE") == 0 ||\r
-          stricmp (ModuleType, "BS_DRIVER") == 0  ||\r
-          stricmp (ModuleType, "DXE_DRIVER") == 0 ||\r
-          stricmp (ModuleType, "DXE_SMM_DRIVER") == 0  ||\r
-          stricmp (ModuleType, "UEFI_DRIVER") == 0 ||\r
-          stricmp (ModuleType, "SMM_CORE") == 0) {\r
-        Type = EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER;\r
-        VerboseMsg ("Efi Image subsystem type is efi boot service driver.");\r
+        stricmp (ModuleType, "SEC") == 0 ||\r
+        stricmp (ModuleType, "SECURITY_CORE") == 0 ||\r
+        stricmp (ModuleType, "PEI_CORE") == 0 ||\r
+        stricmp (ModuleType, "PEIM") == 0 ||\r
+        stricmp (ModuleType, "COMBINED_PEIM_DRIVER") == 0 ||\r
+        stricmp (ModuleType, "PIC_PEIM") == 0 ||\r
+        stricmp (ModuleType, "RELOCATABLE_PEIM") == 0 ||\r
+        stricmp (ModuleType, "DXE_CORE") == 0 ||\r
+        stricmp (ModuleType, "BS_DRIVER") == 0  ||\r
+        stricmp (ModuleType, "DXE_DRIVER") == 0 ||\r
+        stricmp (ModuleType, "DXE_SMM_DRIVER") == 0  ||\r
+        stricmp (ModuleType, "UEFI_DRIVER") == 0 ||\r
+        stricmp (ModuleType, "SMM_CORE") == 0) {\r
+          Type = EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER;\r
+          VerboseMsg ("Efi Image subsystem type is efi boot service driver.");\r
 \r
       } else if (stricmp (ModuleType, "UEFI_APPLICATION") == 0 ||\r
-                 stricmp (ModuleType, "APPLICATION") == 0) {\r
-        Type = EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION;\r
-        VerboseMsg ("Efi Image subsystem type is efi application.");\r
+        stricmp (ModuleType, "APPLICATION") == 0) {\r
+          Type = EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION;\r
+          VerboseMsg ("Efi Image subsystem type is efi application.");\r
 \r
       } else if (stricmp (ModuleType, "DXE_RUNTIME_DRIVER") == 0 ||\r
-                 stricmp (ModuleType, "RT_DRIVER") == 0) {\r
-        Type = EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER;\r
-        VerboseMsg ("Efi Image subsystem type is efi runtime driver.");\r
+        stricmp (ModuleType, "RT_DRIVER") == 0) {\r
+          Type = EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER;\r
+          VerboseMsg ("Efi Image subsystem type is efi runtime driver.");\r
 \r
       } else if (stricmp (ModuleType, "DXE_SAL_DRIVER") == 0 ||\r
-                 stricmp (ModuleType, "SAL_RT_DRIVER") == 0) {\r
-        Type = EFI_IMAGE_SUBSYSTEM_SAL_RUNTIME_DRIVER;\r
-        VerboseMsg ("Efi Image subsystem type is efi sal runtime driver.");\r
+        stricmp (ModuleType, "SAL_RT_DRIVER") == 0) {\r
+          Type = EFI_IMAGE_SUBSYSTEM_SAL_RUNTIME_DRIVER;\r
+          VerboseMsg ("Efi Image subsystem type is efi sal runtime driver.");\r
 \r
       } else {\r
         Error (NULL, 0, 1003, "Invalid option value", "EFI_FILETYPE = %s", ModuleType);\r
@@ -2559,7 +2893,7 @@ Returns:
     VerboseMsg ("Convert the input ELF Image to Pe Image");\r
     ConvertElf(&FileBuffer, &FileLength);\r
   }\r
\r
+\r
   //\r
   // Make sure File Offsets and Virtual Offsets are the same in the image so it is XIP\r
   // XIP == eXecute In Place\r
@@ -2583,15 +2917,15 @@ Returns:
           //\r
           if ((SectionHeader->PointerToRawData + SectionHeader->SizeOfRawData) ==\r
             (FileLength + TeHdr->StrippedSize - sizeof (EFI_TE_IMAGE_HEADER))) {\r
-            //\r
-            // Remove .reloc section and update TeImage Header\r
-            //\r
-            FileLength = FileLength - SectionHeader->SizeOfRawData;\r
-            SectionHeader->SizeOfRawData = 0;\r
-            SectionHeader->Misc.VirtualSize = 0;\r
-            TeHdr->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress = 0;\r
-            TeHdr->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size           = 0;\r
-            break;\r
+              //\r
+              // Remove .reloc section and update TeImage Header\r
+              //\r
+              FileLength = FileLength - SectionHeader->SizeOfRawData;\r
+              SectionHeader->SizeOfRawData = 0;\r
+              SectionHeader->Misc.VirtualSize = 0;\r
+              TeHdr->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress = 0;\r
+              TeHdr->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size           = 0;\r
+              break;\r
           }\r
         }\r
       }\r
@@ -2677,13 +3011,50 @@ Returns:
       goto Finish;\r
     }\r
   }\r
-  \r
+\r
   if (PeHdr->Pe32.FileHeader.Machine == IMAGE_FILE_MACHINE_ARM) {\r
     // Some tools kick out IMAGE_FILE_MACHINE_ARM (0x1c0) vs IMAGE_FILE_MACHINE_ARMT (0x1c2)\r
     // so patch back to the offical UEFI value.\r
     PeHdr->Pe32.FileHeader.Machine = IMAGE_FILE_MACHINE_ARMT;\r
   }\r
 \r
+  //\r
+  // Set new base address into image\r
+  //\r
+  if (OutImageType == FW_REBASE_IMAGE || OutImageType == FW_SET_ADDRESS_IMAGE) {\r
+    if ((PeHdr->Pe32.OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) && (PeHdr->Pe32.FileHeader.Machine != IMAGE_FILE_MACHINE_IA64)) {\r
+      if (NewBaseAddress >= 0x100000000ULL) {\r
+        Error (NULL, 0, 3000, "Invalid", "New base address is larger than 4G for 32bit PE image");\r
+        goto Finish;\r
+      }\r
+    }\r
+    \r
+    if (NegativeAddr) {\r
+      //\r
+      // Set Base Address to a negative value.\r
+      //\r
+      NewBaseAddress = (UINT64) (0 - NewBaseAddress);\r
+    }\r
+    if (OutImageType == FW_REBASE_IMAGE) {\r
+      Status = RebaseImage (mInImageName, FileBuffer, NewBaseAddress);\r
+    } else {\r
+      Status = SetAddressToSectionHeader (mInImageName, FileBuffer, NewBaseAddress);\r
+    }\r
+    if (EFI_ERROR (Status)) {\r
+      if (NegativeAddr) {\r
+        Error (NULL, 0, 3000, "Invalid", "Rebase/Set Image %s to Base address -0x%llx can't success", mInImageName, 0 - NewBaseAddress);\r
+      } else {\r
+        Error (NULL, 0, 3000, "Invalid", "Rebase/Set Image %s to Base address 0x%llx can't success", mInImageName, NewBaseAddress);\r
+      }\r
+      goto Finish;\r
+    }\r
+\r
+    //\r
+    // Write file\r
+    //\r
+    goto WriteFile;\r
+  }\r
+\r
   //\r
   // Extract bin data from Pe image.\r
   //\r
@@ -2695,14 +3066,10 @@ Returns:
     //\r
     // Output bin data from exe file\r
     //\r
-    if (fpOut != NULL) {\r
-      fwrite (FileBuffer + PeHdr->Pe32.OptionalHeader.SizeOfHeaders, 1, FileLength - PeHdr->Pe32.OptionalHeader.SizeOfHeaders, fpOut);\r
-    }\r
-    if (fpInOut != NULL) {\r
-      fwrite (FileBuffer + PeHdr->Pe32.OptionalHeader.SizeOfHeaders, 1, FileLength - PeHdr->Pe32.OptionalHeader.SizeOfHeaders, fpInOut);\r
-    }\r
-    VerboseMsg ("the size of output file is %u bytes", (unsigned) (FileLength - PeHdr->Pe32.OptionalHeader.SizeOfHeaders));\r
-    goto Finish;\r
+    FileLength = FileLength - PeHdr->Pe32.OptionalHeader.SizeOfHeaders;\r
+    memcpy (FileBuffer, FileBuffer + PeHdr->Pe32.OptionalHeader.SizeOfHeaders, FileLength);\r
+    VerboseMsg ("the size of output file is %u bytes", (unsigned) FileLength);\r
+    goto WriteFile;\r
   }\r
 \r
   //\r
@@ -2715,14 +3082,11 @@ Returns:
       goto Finish;\r
     }\r
 \r
-    if (fpOut != NULL) {\r
-      fwrite (FileBuffer, 1, FileLength, fpOut);\r
-    }\r
-    if (fpInOut != NULL) {\r
-      fwrite (FileBuffer, 1, FileLength, fpInOut);\r
-    }\r
+    //\r
+    // Write the updated Image\r
+    //\r
     VerboseMsg ("the size of output file is %u bytes", (unsigned) FileLength);\r
-    goto Finish;\r
+    goto WriteFile;\r
   }\r
 \r
   //\r
@@ -2734,14 +3098,11 @@ Returns:
       goto Finish;\r
     }\r
 \r
-    if (fpOut != NULL) {\r
-      fwrite (FileBuffer, 1, FileLength, fpOut);\r
-    }\r
-    if (fpInOut != NULL) {\r
-      fwrite (FileBuffer, 1, FileLength, fpInOut);\r
-    }\r
+    //\r
+    // Write the updated Image\r
+    //\r
     VerboseMsg ("the size of output file is %u bytes", (unsigned) FileLength);\r
-    goto Finish;\r
+    goto WriteFile;\r
   }\r
 \r
   //\r
@@ -2768,14 +3129,9 @@ Returns:
         //\r
         // Output Apci data to file\r
         //\r
-        if (fpOut != NULL) {\r
-          fwrite (FileBuffer + SectionHeader->PointerToRawData, 1, FileLength, fpOut);\r
-        }\r
-        if (fpInOut != NULL) {\r
-          fwrite (FileBuffer + SectionHeader->PointerToRawData, 1, FileLength, fpInOut);\r
-        }\r
+        memcpy (FileBuffer, FileBuffer + SectionHeader->PointerToRawData, FileLength);\r
         VerboseMsg ("the size of output file is %u bytes", (unsigned) FileLength);\r
-        goto Finish;\r
+        goto WriteFile;\r
       }\r
     }\r
     Error (NULL, 0, 3000, "Invalid", "failed to get ACPI table from %s.", mInImageName);\r
@@ -2789,7 +3145,7 @@ Returns:
     memset (DosHdr, 0, sizeof (EFI_IMAGE_DOS_HEADER));\r
     DosHdr->e_magic  = BackupDosHdr.e_magic;\r
     DosHdr->e_lfanew = BackupDosHdr.e_lfanew;\r
-  \r
+\r
     for (Index = sizeof (EFI_IMAGE_DOS_HEADER); Index < (UINT32 ) DosHdr->e_lfanew; Index++) {\r
       FileBuffer[Index] = (UINT8) DosHdr->e_cp;\r
     }\r
@@ -2804,7 +3160,7 @@ Returns:
   TEImageHeader.NumberOfSections = (UINT8) PeHdr->Pe32.FileHeader.NumberOfSections;\r
   TEImageHeader.StrippedSize     = (UINT16) ((UINTN) ((UINT8 *) &(PeHdr->Pe32.OptionalHeader) + PeHdr->Pe32.FileHeader.SizeOfOptionalHeader) - (UINTN) FileBuffer);\r
   TEImageHeader.Subsystem        = (UINT8) Type;\r
-  \r
+\r
   //\r
   // Patch the PE header\r
   //\r
@@ -2845,28 +3201,28 @@ Returns:
     // Zero .pdata section data.\r
     //\r
     if (!KeepExceptionTableFlag && Optional32->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION &&\r
-        Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION].VirtualAddress != 0 &&\r
-        Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION].Size != 0) {\r
-      SectionHeader = (EFI_IMAGE_SECTION_HEADER *) ((UINT8 *) &(PeHdr->Pe32.OptionalHeader) + PeHdr->Pe32.FileHeader.SizeOfOptionalHeader);\r
-      for (Index = 0; Index < PeHdr->Pe32.FileHeader.NumberOfSections; Index++, SectionHeader++) {\r
-        if (SectionHeader->VirtualAddress == Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION].VirtualAddress) {\r
-          //\r
-          // Zero .pdata Section data\r
-          //\r
-          memset (FileBuffer + SectionHeader->PointerToRawData, 0, SectionHeader->SizeOfRawData);\r
-          //\r
-          // Zero .pdata Section header name\r
-          //\r
-          memset (SectionHeader->Name, 0, sizeof (SectionHeader->Name));\r
-          //\r
-          // Zero Execption Table\r
-          //\r
-          Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION].VirtualAddress = 0;\r
-          Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION].Size           = 0;\r
-          DebugMsg (NULL, 0, 9, "Zero the .pdata section for PE image", NULL);\r
-          break;\r
+      Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION].VirtualAddress != 0 &&\r
+      Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION].Size != 0) {\r
+        SectionHeader = (EFI_IMAGE_SECTION_HEADER *) ((UINT8 *) &(PeHdr->Pe32.OptionalHeader) + PeHdr->Pe32.FileHeader.SizeOfOptionalHeader);\r
+        for (Index = 0; Index < PeHdr->Pe32.FileHeader.NumberOfSections; Index++, SectionHeader++) {\r
+          if (SectionHeader->VirtualAddress == Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION].VirtualAddress) {\r
+            //\r
+            // Zero .pdata Section data\r
+            //\r
+            memset (FileBuffer + SectionHeader->PointerToRawData, 0, SectionHeader->SizeOfRawData);\r
+            //\r
+            // Zero .pdata Section header name\r
+            //\r
+            memset (SectionHeader->Name, 0, sizeof (SectionHeader->Name));\r
+            //\r
+            // Zero Execption Table\r
+            //\r
+            Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION].VirtualAddress = 0;\r
+            Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION].Size           = 0;\r
+            DebugMsg (NULL, 0, 9, "Zero the .pdata section for PE image", NULL);\r
+            break;\r
+          }\r
         }\r
-      }\r
     }\r
 \r
     //\r
@@ -2941,40 +3297,40 @@ Returns:
     //\r
     if ((!KeepExceptionTableFlag && PeHdr->Pe32.FileHeader.Machine == IMAGE_FILE_MACHINE_X64) || PeHdr->Pe32.FileHeader.Machine == IMAGE_FILE_MACHINE_IA64) {\r
       if (Optional64->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION &&\r
-          Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION].VirtualAddress != 0 &&\r
-          Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION].Size != 0) {\r
-        SectionHeader = (EFI_IMAGE_SECTION_HEADER *) ((UINT8 *) &(PeHdr->Pe32.OptionalHeader) + PeHdr->Pe32.FileHeader.SizeOfOptionalHeader);\r
-        for (Index = 0; Index < PeHdr->Pe32.FileHeader.NumberOfSections; Index++, SectionHeader++) {\r
-          if (SectionHeader->VirtualAddress == Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION].VirtualAddress) {\r
-            //\r
-            // Zero .pdata Section header name\r
-            //\r
-            memset (SectionHeader->Name, 0, sizeof (SectionHeader->Name));\r
-\r
-            RuntimeFunction = (RUNTIME_FUNCTION *)(FileBuffer + SectionHeader->PointerToRawData);\r
-            for (Index1 = 0; Index1 < Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION].Size / sizeof (RUNTIME_FUNCTION); Index1++, RuntimeFunction++) {\r
-              SectionHeader = (EFI_IMAGE_SECTION_HEADER *) ((UINT8 *) &(PeHdr->Pe32.OptionalHeader) + PeHdr->Pe32.FileHeader.SizeOfOptionalHeader);\r
-              for (Index2 = 0; Index2 < PeHdr->Pe32.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
+        Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION].VirtualAddress != 0 &&\r
+        Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION].Size != 0) {\r
+          SectionHeader = (EFI_IMAGE_SECTION_HEADER *) ((UINT8 *) &(PeHdr->Pe32.OptionalHeader) + PeHdr->Pe32.FileHeader.SizeOfOptionalHeader);\r
+          for (Index = 0; Index < PeHdr->Pe32.FileHeader.NumberOfSections; Index++, SectionHeader++) {\r
+            if (SectionHeader->VirtualAddress == Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION].VirtualAddress) {\r
+              //\r
+              // Zero .pdata Section header name\r
+              //\r
+              memset (SectionHeader->Name, 0, sizeof (SectionHeader->Name));\r
+\r
+              RuntimeFunction = (RUNTIME_FUNCTION *)(FileBuffer + SectionHeader->PointerToRawData);\r
+              for (Index1 = 0; Index1 < Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION].Size / sizeof (RUNTIME_FUNCTION); Index1++, RuntimeFunction++) {\r
+                SectionHeader = (EFI_IMAGE_SECTION_HEADER *) ((UINT8 *) &(PeHdr->Pe32.OptionalHeader) + PeHdr->Pe32.FileHeader.SizeOfOptionalHeader);\r
+                for (Index2 = 0; Index2 < PeHdr->Pe32.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
+                    break;\r
                   }\r
-                  break;\r
                 }\r
+                memset (RuntimeFunction, 0, sizeof (RUNTIME_FUNCTION));\r
               }\r
-              memset (RuntimeFunction, 0, sizeof (RUNTIME_FUNCTION));\r
+              //\r
+              // Zero Execption Table\r
+              //\r
+              Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION].Size = 0;\r
+              Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION].VirtualAddress = 0;\r
+              DebugMsg (NULL, 0, 9, "Zero the .pdata section if the machine type is X64 for PE32+ image", NULL);\r
+              break;\r
             }\r
-            //\r
-            // Zero Execption Table\r
-            //\r
-            Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION].Size = 0;\r
-            Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION].VirtualAddress = 0;\r
-            DebugMsg (NULL, 0, 9, "Zero the .pdata section if the machine type is X64 for PE32+ image", NULL);\r
-            break;\r
           }\r
-        }\r
       }\r
     }\r
 \r
@@ -3017,19 +3373,19 @@ Returns:
     Error (NULL, 0, 3000, "Invalid", "Magic 0x%x of PeImage %s is unknown.", PeHdr->Pe32.OptionalHeader.Magic, mInImageName);\r
     goto Finish;\r
   }\r
-  \r
+\r
   if (((PeHdr->Pe32.FileHeader.Characteristics & EFI_IMAGE_FILE_RELOCS_STRIPPED) == 0) && \\r
     (TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress == 0) && \\r
     (TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size == 0)) {\r
-    //\r
-    // PeImage can be loaded into memory, but it has no relocation section. \r
-    // Fix TeImage Header to set VA of relocation data directory to not zero, the size is still zero.\r
-    //\r
-    if (Optional32 != NULL) {\r
-      TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress = Optional32->SizeOfImage - sizeof (EFI_IMAGE_BASE_RELOCATION);\r
-    } else if (Optional64 != NULL) {\r
-      TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress = Optional64->SizeOfImage - sizeof (EFI_IMAGE_BASE_RELOCATION);\r
-    }\r
+      //\r
+      // PeImage can be loaded into memory, but it has no relocation section. \r
+      // Fix TeImage Header to set VA of relocation data directory to not zero, the size is still zero.\r
+      //\r
+      if (Optional32 != NULL) {\r
+        TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress = Optional32->SizeOfImage - sizeof (EFI_IMAGE_BASE_RELOCATION);\r
+      } else if (Optional64 != NULL) {\r
+        TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress = Optional64->SizeOfImage - sizeof (EFI_IMAGE_BASE_RELOCATION);\r
+      }\r
   }\r
 \r
   //\r
@@ -3102,40 +3458,54 @@ Returns:
     }\r
 \r
     DebugMsg (NULL, 0, 9, "TeImage Header Info", "Machine type is %X, Number of sections is %X, Stripped size is %X, EntryPoint is %X, BaseOfCode is %X, ImageBase is %llX",\r
-              TEImageHeader.Machine, TEImageHeader.NumberOfSections, TEImageHeader.StrippedSize, (unsigned) TEImageHeader.AddressOfEntryPoint, (unsigned) TEImageHeader.BaseOfCode, (unsigned long long) TEImageHeader.ImageBase);\r
+      TEImageHeader.Machine, TEImageHeader.NumberOfSections, TEImageHeader.StrippedSize, (unsigned) TEImageHeader.AddressOfEntryPoint, (unsigned) TEImageHeader.BaseOfCode, (unsigned long long) TEImageHeader.ImageBase);\r
     //\r
     // Update Image to TeImage\r
     //\r
-    if (fpOut != NULL) {\r
-      fwrite (&TEImageHeader, 1, sizeof (EFI_TE_IMAGE_HEADER), fpOut);\r
-      fwrite (FileBuffer + TEImageHeader.StrippedSize, 1, FileLength - TEImageHeader.StrippedSize, fpOut);\r
-    }\r
-    if (fpInOut != NULL) {\r
-      fwrite (&TEImageHeader, 1, sizeof (EFI_TE_IMAGE_HEADER), fpInOut);\r
-      fwrite (FileBuffer + TEImageHeader.StrippedSize, 1, FileLength - TEImageHeader.StrippedSize, fpInOut);\r
-    }\r
-    VerboseMsg ("the size of output file is %u bytes", (unsigned) (FileLength - TEImageHeader.StrippedSize));\r
-    goto Finish;\r
+    FileLength = FileLength - TEImageHeader.StrippedSize;\r
+    memcpy (FileBuffer + sizeof (EFI_TE_IMAGE_HEADER), FileBuffer + TEImageHeader.StrippedSize, FileLength);\r
+    FileLength = FileLength + sizeof (EFI_TE_IMAGE_HEADER);\r
+    memcpy (FileBuffer, &TEImageHeader, sizeof (EFI_TE_IMAGE_HEADER));\r
+    VerboseMsg ("the size of output file is %u bytes", (unsigned) (FileLength));\r
   }\r
+\r
 WriteFile:\r
   //\r
-  // Update Image to EfiImage\r
+  // Update Image to EfiImage or TE image\r
   //\r
-  if (fpOut != NULL) {\r
-    fwrite (FileBuffer, 1, FileLength, fpOut);\r
-  }\r
-  if (fpInOut != NULL) {\r
-    fwrite (FileBuffer, 1, FileLength, fpInOut);\r
+  if (ReplaceFlag) {\r
+    if ((FileLength != InputFileLength) || (memcmp (FileBuffer, InputFileBuffer, FileLength) != 0)) {\r
+      //\r
+      // Update File when File is changed.\r
+      //\r
+      fpInOut = fopen (mInImageName, "wb");\r
+      if (fpInOut == NULL) {\r
+        Error (NULL, 0, 0001, "Error opening file", mInImageName);\r
+        goto Finish;\r
+      }\r
+      fwrite (FileBuffer, 1, FileLength, fpInOut);\r
+      VerboseMsg ("the size of output file is %u bytes", (unsigned) FileLength);\r
+    }\r
+  } else {\r
+    if ((FileLength != OutputFileLength) || (memcmp (FileBuffer, OutputFileBuffer, FileLength) != 0)) {\r
+      fpOut = fopen (OutImageName, "wb");\r
+      if (fpOut == NULL) {\r
+        Error (NULL, 0, 0001, "Error opening output file", OutImageName);\r
+        goto Finish;\r
+      }\r
+      fwrite (FileBuffer, 1, FileLength, fpOut);\r
+      VerboseMsg ("the size of output file is %u bytes", (unsigned) FileLength);\r
+    }\r
   }\r
-  VerboseMsg ("the size of output file is %u bytes", (unsigned) FileLength);\r
+  mImageSize = FileLength;\r
 \r
 Finish:\r
   if (fpInOut != NULL) {\r
     if (GetUtilityStatus () != STATUS_SUCCESS) {\r
       //\r
-      // when file updates failed, original file is still recoveried.\r
+      // when file updates failed, original file is still recovered.\r
       //\r
-      fwrite (FileBuffer, 1, FileLength, fpInOut);\r
+      fwrite (InputFileBuffer, 1, InputFileLength, fpInOut);\r
     }\r
     //\r
     // Write converted data into fpInOut file and close input file.\r
@@ -3163,11 +3533,38 @@ Finish:
         fpOut = fopen (OutImageName, "wb");\r
         fwrite (OutputFileBuffer, 1, OutputFileLength, fpOut);\r
         fclose (fpOut);\r
-        free (OutputFileBuffer);\r
       }\r
     }\r
   }\r
+  \r
+  if (InputFileBuffer != NULL) {\r
+    free (InputFileBuffer);\r
+  }\r
+\r
+  if (OutputFileBuffer != NULL) {\r
+    free (OutputFileBuffer);\r
+  }\r
 \r
+  //\r
+  // Write module size and time stamp to report file.\r
+  //\r
+  if (OutImageName != NULL) {\r
+    FileLen = strlen (OutImageName);\r
+  }\r
+  if (FileLen >= 4 && strcmp (OutImageName + (FileLen - 4), ".efi") == 0) {\r
+    ReportFileName = (CHAR8 *) malloc (FileLen + 1);\r
+    if (ReportFileName != NULL) {\r
+      strcpy (ReportFileName, OutImageName);\r
+      strcpy (ReportFileName + (FileLen - 4), ".txt"); \r
+      ReportFile = fopen (ReportFileName, "w+");\r
+      if (ReportFile != NULL) {\r
+        fprintf (ReportFile, "MODULE_SIZE = %u\n", (unsigned) mImageSize);\r
+        fprintf (ReportFile, "TIME_STAMP = %u\n", (unsigned) mImageTimeStamp);\r
+        fclose(ReportFile);\r
+      }\r
+      free (ReportFileName);\r
+    }\r
+  }\r
   VerboseMsg ("%s tool done with return code is 0x%x.", UTILITY_NAME, GetUtilityStatus ());\r
 \r
   return GetUtilityStatus ();\r
@@ -3302,7 +3699,7 @@ Returns:
   //Zero Debug Data and TimeStamp\r
   //\r
   FileHdr->TimeDateStamp = 0;\r
-\r
+  mImageTimeStamp = 0;\r
   if (ExportDirectoryEntryFileOffset != 0) {\r
     NewTimeStamp  = (UINT32 *) (FileBuffer + ExportDirectoryEntryFileOffset + sizeof (UINT32));\r
     *NewTimeStamp = 0;\r
@@ -3316,6 +3713,7 @@ Returns:
   if (DebugDirectoryEntryFileOffset != 0) {\r
     DebugEntry = (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY *) (FileBuffer + DebugDirectoryEntryFileOffset);\r
     DebugEntry->TimeDateStamp = 0;\r
+    mImageTimeStamp = 0;\r
     if (ZeroDebugFlag) {\r
       memset (FileBuffer + DebugEntry->FileOffset, 0, DebugEntry->SizeOfData);\r
       memset (DebugEntry, 0, sizeof (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY));\r
@@ -3542,7 +3940,7 @@ Returns:
   // Set new stamp\r
   //\r
   FileHdr->TimeDateStamp = (UINT32) newtime;\r
-\r
+  mImageTimeStamp = (UINT32) newtime;\r
   if (ExportDirectoryEntryRva != 0) {\r
     NewTimeStamp  = (UINT32 *) (FileBuffer + ExportDirectoryEntryFileOffset + sizeof (UINT32));\r
     *NewTimeStamp = (UINT32) newtime;\r