Update GenFw to support rebase image to the specified address.
authorlgao4 <lgao4@c2973edb-eda0-4c78-bc6a-9341b269661f>
Thu, 28 Jan 2010 10:28:04 +0000 (10:28 +0000)
committerlgao4 <lgao4@c2973edb-eda0-4c78-bc6a-9341b269661f>
Thu, 28 Jan 2010 10:28:04 +0000 (10:28 +0000)
git-svn-id: https://edk2-buildtools.svn.sourceforge.net/svnroot/edk2-buildtools/trunk/BaseTools@1822 c2973edb-eda0-4c78-bc6a-9341b269661f

Source/C/GenFw/GenFw.c

index a7091bd..5412bd4 100644 (file)
@@ -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
@@ -196,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
@@ -294,6 +296,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
@@ -1646,6 +1660,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
@@ -1693,6 +1958,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
@@ -1719,6 +1986,8 @@ 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
@@ -1728,6 +1997,7 @@ Returns:
   //\r
   // Assign to fix compile warning\r
   //\r
+  FileLen           = 0;\r
   InputFileNum      = 0;\r
   InputFileName     = NULL;\r
   mInImageName      = NULL;\r
@@ -1750,6 +2020,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
@@ -1762,6 +2034,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
@@ -1909,6 +2183,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
@@ -1952,7 +2264,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
@@ -1998,9 +2310,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
@@ -2100,6 +2412,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
@@ -2124,33 +2442,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
@@ -2196,7 +2533,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
@@ -2250,7 +2587,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
@@ -2272,6 +2609,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
@@ -2316,7 +2661,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
@@ -2410,63 +2755,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
@@ -2476,6 +2779,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
@@ -2489,7 +2812,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
@@ -2524,36 +2846,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
@@ -2569,7 +2891,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
@@ -2593,15 +2915,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
@@ -2687,13 +3009,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
@@ -2705,14 +3064,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
@@ -2725,14 +3080,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
@@ -2744,14 +3096,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
@@ -2778,14 +3127,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
@@ -2799,7 +3143,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
@@ -2814,7 +3158,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
@@ -2855,28 +3199,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
@@ -2951,40 +3295,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
@@ -3027,19 +3371,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
@@ -3112,41 +3456,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
@@ -3174,15 +3531,24 @@ 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
-  FileLen = strlen (OutImageName);\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