]> git.proxmox.com Git - mirror_edk2.git/blobdiff - BaseTools/Source/C/GenFw/GenFw.c
BaseTools: Fix Segmentation fault: 11 when build AppPkg with XCODE5
[mirror_edk2.git] / BaseTools / Source / C / GenFw / GenFw.c
index d570f633d531a76f7e5f3eac67ac47a3b43b8d2d..af60c92763c4c8020559d46972e5f8321c460f00 100644 (file)
@@ -1,7 +1,8 @@
 /** @file\r
+Converts a pe32+ image to an FW, Te image type, or other specific image.\r
 \r
-Copyright (c) 2004 - 2009, Intel Corporation\r
-All rights reserved. This program and the accompanying materials\r
+Copyright (c) 2004 - 2016, Intel Corporation. All rights reserved.<BR>\r
+This program and the accompanying materials\r
 are licensed and made available under the terms and conditions of the BSD License\r
 which accompanies this distribution.  The full text of the license may be found at\r
 http://opensource.org/licenses/bsd-license.php\r
@@ -9,20 +10,15 @@ http://opensource.org/licenses/bsd-license.php
 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
 \r
-Module Name:\r
-\r
-    GenFw.c\r
-\r
-Abstract:\r
-\r
-    Converts a pe32+ image to an FW, Te image type, or other specific image.\r
-\r
 **/\r
 \r
 #include "WinNtInclude.h"\r
 \r
 #ifndef __GNUC__\r
 #include <windows.h>\r
+#include <io.h>\r
+#include <sys/types.h>\r
+#include <sys/stat.h>\r
 #endif\r
 #include <stdio.h>\r
 #include <stdlib.h>\r
@@ -32,6 +28,7 @@ Abstract:
 \r
 #include <Common/UefiBaseTypes.h>\r
 #include <IndustryStandard/PeImage.h>\r
+#include <Common/UefiInternalFormRepresentation.h>\r
 \r
 //\r
 // Acpi Table definition\r
@@ -43,12 +40,11 @@ Abstract:
 #include <IndustryStandard/MemoryMappedConfigurationSpaceAccessTable.h>\r
 \r
 #include "CommonLib.h"\r
+#include "PeCoffLib.h"\r
+#include "ParseInf.h"\r
 #include "EfiUtilityMsgs.h"\r
 \r
-#include "elf_common.h"\r
-#include "elf32.h"\r
-#include "elf64.h"\r
-\r
+#include "GenFw.h"\r
 \r
 //\r
 // Version of this utility\r
@@ -57,30 +53,13 @@ Abstract:
 #define UTILITY_MAJOR_VERSION 0\r
 #define UTILITY_MINOR_VERSION 2\r
 \r
-//\r
-// Action for this tool.\r
-//\r
-#define FW_DUMMY_IMAGE       0\r
-#define FW_EFI_IMAGE         1\r
-#define FW_TE_IMAGE          2\r
-#define FW_ACPI_IMAGE        3\r
-#define FW_BIN_IMAGE         4\r
-#define FW_ZERO_DEBUG_IMAGE  5\r
-#define FW_SET_STAMP_IMAGE   6\r
-#define FW_MCI_IMAGE         7\r
-#define FW_MERGE_IMAGE       8\r
-#define FW_RELOC_STRIPEED_IMAGE 9\r
-\r
-#define DUMP_TE_HEADER       0x11\r
+#define HII_RESOURCE_SECTION_INDEX  1\r
+#define HII_RESOURCE_SECTION_NAME   "HII"\r
 \r
 #define DEFAULT_MC_PAD_BYTE_VALUE  0xFF\r
 #define DEFAULT_MC_ALIGNMENT       16\r
 \r
-#ifndef _MAX_PATH\r
-#define _MAX_PATH 500\r
-#endif\r
-\r
-#define STATUS_IGNORE        0xA\r
+#define STATUS_IGNORE 0xA\r
 //\r
 // Structure definition for a microcode header\r
 //\r
@@ -97,7 +76,23 @@ typedef struct {
   UINT32  Reserved[3];\r
 } MICROCODE_IMAGE_HEADER;\r
 \r
-STATIC CHAR8 *mInImageName;\r
+static EFI_GUID mZeroGuid = {0x0, 0x0, 0x0, {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}};\r
+\r
+static const char *gHiiPackageRCFileHeader[] = {\r
+  "//",\r
+  "//  DO NOT EDIT -- auto-generated file",\r
+  "//",\r
+  NULL\r
+};\r
+\r
+//\r
+// Module image information\r
+//\r
+CHAR8  *mInImageName;\r
+UINT32 mImageTimeStamp = 0;\r
+UINT32 mImageSize = 0;\r
+UINT32 mOutImageType = FW_DUMMY_IMAGE;\r
+\r
 \r
 STATIC\r
 EFI_STATUS\r
@@ -141,7 +136,7 @@ Returns:
 \r
 --*/\r
 {\r
-  fprintf (stdout, "%s Version %d.%d\n", UTILITY_NAME, UTILITY_MAJOR_VERSION, UTILITY_MINOR_VERSION);\r
+  fprintf (stdout, "%s Version %d.%d %s \n", UTILITY_NAME, UTILITY_MAJOR_VERSION, UTILITY_MINOR_VERSION, __BUILD_VERSION);\r
 }\r
 \r
 STATIC\r
@@ -173,7 +168,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 - 2015, Intel Corporation. All rights reserved.\n\n");\r
 \r
   //\r
   // Details Option\r
@@ -182,16 +177,17 @@ Returns:
   fprintf (stdout, "  -o FileName, --outputfile FileName\n\\r
                         File will be created to store the ouput content.\n");\r
   fprintf (stdout, "  -e EFI_FILETYPE, --efiImage EFI_FILETYPE\n\\r
-                        Create Efi Image. EFI_FILETYPE is one of BASE, SEC,\n\\r
+                        Create Efi Image. EFI_FILETYPE is one of BASE,SMM_CORE,\n\\r
                         PEI_CORE, PEIM, DXE_CORE, DXE_DRIVER, UEFI_APPLICATION,\n\\r
-                        DXE_SAL_DRIVER, UEFI_DRIVER, DXE_RUNTIME_DRIVER, \n\\r
-                        DXE_SMM_DRIVER, SECURITY_CORE, COMBINED_PEIM_DRIVER, \n\\r
+                        SEC, DXE_SAL_DRIVER, UEFI_DRIVER, DXE_RUNTIME_DRIVER,\n\\r
+                        DXE_SMM_DRIVER, SECURITY_CORE, COMBINED_PEIM_DRIVER,\n\\r
+                        MM_STANDALONE, MM_CORE_STANDALONE,\n\\r
                         PIC_PEIM, RELOCATABLE_PEIM, BS_DRIVER, RT_DRIVER,\n\\r
                         APPLICATION, SAL_RT_DRIVER to support all module types\n\\r
                         It can only be used together with --keepexceptiontable,\n\\r
-                        --keepzeropending, -r, -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
+                        --keepzeropending, --keepoptionalheader, -r, -o option.\n\\r
+                        It is a action option. If it is combined with other action options,\n\\r
+                        the later input action option will override the previous one.\n");\r
   fprintf (stdout, "  -c, --acpi            Create Acpi table.\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
@@ -199,9 +195,9 @@ Returns:
                         input action option will override the previous one.\n");\r
   fprintf (stdout, "  -t, --terse           Create Te Image.\n\\r
                         It can only be used together with --keepexceptiontable,\n\\r
-                        --keepzeropending, -r, -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
+                        --keepzeropending, --keepoptionalheader, -r, -o option.\n\\r
+                        It is a action option. If it is combined with other action options,\n\\r
+                        the later input action option will override the previous one.\n");\r
   fprintf (stdout, "  -u, --dump            Dump TeImage Header.\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
@@ -219,7 +215,7 @@ Returns:
                         except for -o, -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, "  -l, --stripped        Relocation info stripped from the input PE or TE image.\n\\r
+  fprintf (stdout, "  -l, --stripped        Strip off the relocation info from PE or TE image.\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
@@ -227,7 +223,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
@@ -249,12 +247,43 @@ Returns:
   fprintf (stdout, "  --keepexceptiontable  Don't clear exception table.\n\\r
                         This option can be used together with -e or -t.\n\\r
                         It doesn't work for other options.\n");\r
+  fprintf (stdout, "  --keepoptionalheader  Don't zero PE/COFF optional header fields.\n\\r
+                        This option can be used together with -e or -t.\n\\r
+                        It doesn't work for other options.\n");\r
   fprintf (stdout, "  --keepzeropending     Don't strip zero pending of .reloc.\n\\r
                         This option can be used together with -e or -t.\n\\r
                         It doesn't work for other options.\n");\r
   fprintf (stdout, "  -r, --replace         Overwrite the input file with the output content.\n\\r
                         If more input files are specified,\n\\r
                         the last input file will be as the output file.\n");\r
+  fprintf (stdout, "  -g HiiPackageListGuid, --hiiguid HiiPackageListGuid\n\\r
+                        Guid is used to specify hii package list guid.\n\\r
+                        Its format is xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx\n\\r
+                        If not specified, the first Form FormSet guid is used.\n");\r
+  fprintf (stdout, "  --hiipackage          Combine all input binary hii pacakges into \n\\r
+                        a single package list as the text resource data(RC).\n\\r
+                        It can't be combined with other action options\n\\r
+                        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, "  --hiibinpackage       Combine all input binary hii pacakges into \n\\r
+                        a single package list as the binary resource section.\n\\r
+                        It can't be combined with other action options\n\\r
+                        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
@@ -321,6 +350,10 @@ Returns:
       ExpectedLength = sizeof(EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE);\r
       break;\r
     default:\r
+      if (AcpiHeader->Revision > EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE_REVISION) {\r
+        ExpectedLength = AcpiHeader->Length;\r
+        break;\r
+      }\r
       Error (NULL, 0, 3000, "Invalid", "FACP revision check failed.");\r
       return STATUS_ERROR;\r
     }\r
@@ -335,7 +368,10 @@ Returns:
   //\r
   case EFI_ACPI_3_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_SIGNATURE:\r
     Facs = (EFI_ACPI_3_0_FIRMWARE_ACPI_CONTROL_STRUCTURE *)AcpiTable;\r
-    if ((Facs->Version != 0) &&\r
+    if (Facs->Version > EFI_ACPI_3_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_VERSION) {\r
+      break;\r
+    }\r
+    if ((Facs->Version != EFI_ACPI_1_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_VERSION) &&\r
         (Facs->Version != EFI_ACPI_2_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_VERSION) &&\r
         (Facs->Version != EFI_ACPI_3_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_VERSION)){\r
       Error (NULL, 0, 3000, "Invalid", "FACS version check failed.");\r
@@ -354,8 +390,7 @@ Returns:
   //\r
   case EFI_ACPI_3_0_DIFFERENTIATED_SYSTEM_DESCRIPTION_TABLE_SIGNATURE:\r
     if (AcpiHeader->Revision > EFI_ACPI_3_0_DIFFERENTIATED_SYSTEM_DESCRIPTION_TABLE_REVISION) {\r
-      Error (NULL, 0, 3000, "Invalid", "DSDT revision check failed.");\r
-      return STATUS_ERROR;\r
+      break;\r
     }\r
     if (AcpiHeader->Length <= sizeof(EFI_ACPI_DESCRIPTION_HEADER)) {\r
       Error (NULL, 0, 3000, "Invalid", "DSDT length check failed.");\r
@@ -367,6 +402,9 @@ Returns:
   // "APIC" Multiple APIC Description Table\r
   //\r
   case EFI_ACPI_3_0_MULTIPLE_APIC_DESCRIPTION_TABLE_SIGNATURE:\r
+    if (AcpiHeader->Revision > EFI_ACPI_3_0_MULTIPLE_APIC_DESCRIPTION_TABLE_REVISION) {\r
+      break;\r
+    }\r
     if ((AcpiHeader->Revision != EFI_ACPI_1_0_MULTIPLE_APIC_DESCRIPTION_TABLE_REVISION) &&\r
         (AcpiHeader->Revision != EFI_ACPI_2_0_MULTIPLE_APIC_DESCRIPTION_TABLE_REVISION) &&\r
         (AcpiHeader->Revision != EFI_ACPI_3_0_MULTIPLE_APIC_DESCRIPTION_TABLE_REVISION)) {\r
@@ -383,6 +421,9 @@ Returns:
   // "MCFG" PCI Express Memory Mapped Configuration Space Base Address Description Table\r
   //\r
   case EFI_ACPI_3_0_PCI_EXPRESS_MEMORY_MAPPED_CONFIGURATION_SPACE_BASE_ADDRESS_DESCRIPTION_TABLE_SIGNATURE:\r
+    if (AcpiHeader->Revision > EFI_ACPI_MEMORY_MAPPED_CONFIGURATION_SPACE_ACCESS_TABLE_REVISION) {\r
+      break;\r
+    }\r
     if (AcpiHeader->Revision != EFI_ACPI_MEMORY_MAPPED_CONFIGURATION_SPACE_ACCESS_TABLE_REVISION) {\r
       Error (NULL, 0, 3000, "Invalid", "MCFG revision check failed.");\r
       return STATUS_ERROR;\r
@@ -403,935 +444,591 @@ Returns:
   return STATUS_SUCCESS;\r
 }\r
 \r
-\r
-INTN\r
-IsElfHeader(\r
-  UINT8  *FileBuffer\r
-)\r
-{\r
-  return (FileBuffer[EI_MAG0] == ELFMAG0\r
-    && FileBuffer[EI_MAG1] == ELFMAG1\r
-    && FileBuffer[EI_MAG2] == ELFMAG2\r
-    && FileBuffer[EI_MAG3] == ELFMAG3);\r
-}\r
-\r
-typedef Elf32_Shdr Elf_Shdr;\r
-typedef Elf32_Ehdr Elf_Ehdr;\r
-typedef Elf32_Rel Elf_Rel;\r
-typedef Elf32_Sym Elf_Sym;\r
-typedef Elf32_Phdr Elf_Phdr;\r
-typedef Elf32_Dyn Elf_Dyn;\r
-\r
-#define ELFCLASS ELFCLASS32\r
-#define ELF_R_TYPE(r) ELF32_R_TYPE(r)\r
-#define ELF_R_SYM(r) ELF32_R_SYM(r)\r
-\r
-//\r
-// Well known ELF structures.\r
-//\r
-Elf_Ehdr *Ehdr;\r
-Elf_Shdr *ShdrBase;\r
-Elf_Phdr *gPhdrBase;\r
-\r
-//\r
-// PE section alignment.\r
-//\r
-const UINT32 CoffAlignment = 0x20;\r
-const UINT32 CoffNbrSections = 4;\r
-\r
-//\r
-// Current offset in coff file.\r
-//\r
-UINT32 CoffOffset;\r
-\r
-//\r
-// Result Coff file in memory.\r
-//\r
-UINT8 *CoffFile = NULL;\r
-//\r
-// ELF sections to offset in Coff file.\r
-//\r
-UINT32 *CoffSectionsOffset = NULL;\r
-\r
-//\r
-// Offset in Coff file of headers and sections.\r
-//\r
-UINT32 NtHdrOffset;\r
-UINT32 TableOffset;\r
-UINT32 TextOffset;\r
-UINT32 DataOffset;\r
-UINT32 RelocOffset;\r
-\r
-EFI_IMAGE_BASE_RELOCATION *CoffBaseRel;\r
-UINT16 *CoffEntryRel;\r
-\r
-UINT32\r
-CoffAlign(\r
-  UINT32 Offset\r
-  )\r
-{\r
-  return (Offset + CoffAlignment - 1) & ~(CoffAlignment - 1);\r
-}\r
-\r
-Elf_Shdr *\r
-GetShdrByIndex(\r
-  UINT32 Num\r
+VOID\r
+SetHiiResourceHeader (\r
+  UINT8   *HiiBinData,\r
+  UINT32  OffsetToFile\r
   )\r
 {\r
-  if (Num >= Ehdr->e_shnum)\r
-    return NULL;\r
-  return (Elf_Shdr*)((UINT8*)ShdrBase + Num * Ehdr->e_shentsize);\r
-}\r
+  UINT32  Index;\r
+  EFI_IMAGE_RESOURCE_DIRECTORY        *ResourceDirectory;\r
+  EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY  *ResourceDirectoryEntry;\r
+  EFI_IMAGE_RESOURCE_DIRECTORY_STRING *ResourceDirectoryString;\r
+  EFI_IMAGE_RESOURCE_DATA_ENTRY       *ResourceDataEntry;\r
 \r
-INTN\r
-CheckElfHeader(\r
-  VOID\r
-  )\r
-{\r
   //\r
-  // Note: Magic has already been tested.\r
+  // Fill Resource section entry\r
   //\r
-  if (Ehdr->e_ident[EI_CLASS] != ELFCLASS) {\r
-    Error (NULL, 0, 3000, "Unsupported", "%s needs to be ported for 64-bit ELF.", mInImageName);\r
-    return 0;\r
-  }\r
-  if (Ehdr->e_ident[EI_DATA] != ELFDATA2LSB) {\r
-    Error (NULL, 0, 3000, "Unsupported", "ELF EI_DATA not ELFDATA2LSB");\r
-    return 0;\r
-  }\r
-  if ((Ehdr->e_type != ET_EXEC) && (Ehdr->e_type != ET_DYN)) {\r
-    Error (NULL, 0, 3000, "Unsupported", "ELF e_type not ET_EXEC or ET_DYN");\r
-    return 0;\r
-  }\r
-  if (!((Ehdr->e_machine == EM_386) || (Ehdr->e_machine == EM_ARM))) { \r
-    Error (NULL, 0, 3000, "Unsupported", "ELF e_machine not EM_386 or EM_ARM");\r
-    return 0;\r
-  }\r
-  if (Ehdr->e_version != EV_CURRENT) {\r
-    Error (NULL, 0, 3000, "Unsupported", "ELF e_version (%d) not EV_CURRENT (%d)", Ehdr->e_version, EV_CURRENT);\r
-    return 0;\r
-  }\r
+  ResourceDirectory      = (EFI_IMAGE_RESOURCE_DIRECTORY *) (HiiBinData);\r
+  ResourceDirectoryEntry = (EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY *) (ResourceDirectory + 1);\r
+  for (Index = 0; Index < ResourceDirectory->NumberOfNamedEntries; Index ++) {\r
+    if (ResourceDirectoryEntry->u1.s.NameIsString) {\r
+      ResourceDirectoryString = (EFI_IMAGE_RESOURCE_DIRECTORY_STRING *) (HiiBinData + ResourceDirectoryEntry->u1.s.NameOffset);\r
 \r
-  //\r
-  // Find the section header table\r
-  //\r
-  ShdrBase  = (Elf_Shdr *)((UINT8 *)Ehdr + Ehdr->e_shoff);\r
-  gPhdrBase = (Elf_Phdr *)((UINT8 *)Ehdr + Ehdr->e_phoff);\r
+      if (ResourceDirectoryString->Length == 3 &&\r
+          ResourceDirectoryString->String[0] == L'H' &&\r
+          ResourceDirectoryString->String[1] == L'I' &&\r
+          ResourceDirectoryString->String[2] == L'I') {\r
+        //\r
+        // Resource Type "HII" found\r
+        //\r
+        if (ResourceDirectoryEntry->u2.s.DataIsDirectory) {\r
+          //\r
+          // Move to next level - resource Name\r
+          //\r
+          ResourceDirectory = (EFI_IMAGE_RESOURCE_DIRECTORY *) (HiiBinData + ResourceDirectoryEntry->u2.s.OffsetToDirectory);\r
+          ResourceDirectoryEntry = (EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY *) (ResourceDirectory + 1);\r
 \r
-  CoffSectionsOffset = (UINT32 *)malloc(Ehdr->e_shnum * sizeof (UINT32));\r
+          if (ResourceDirectoryEntry->u2.s.DataIsDirectory) {\r
+            //\r
+            // Move to next level - resource Language\r
+            //\r
+            ResourceDirectory = (EFI_IMAGE_RESOURCE_DIRECTORY *) (HiiBinData + ResourceDirectoryEntry->u2.s.OffsetToDirectory);\r
+            ResourceDirectoryEntry = (EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY *) (ResourceDirectory + 1);\r
+          }\r
+        }\r
 \r
-  memset(CoffSectionsOffset, 0, Ehdr->e_shnum * sizeof(UINT32));\r
-  return 1;\r
+        //\r
+        // Now it ought to be resource Data and update its OffsetToData value \r
+        //\r
+        if (!ResourceDirectoryEntry->u2.s.DataIsDirectory) {\r
+          ResourceDataEntry = (EFI_IMAGE_RESOURCE_DATA_ENTRY *) (HiiBinData + ResourceDirectoryEntry->u2.OffsetToData);\r
+          ResourceDataEntry->OffsetToData = ResourceDataEntry->OffsetToData + OffsetToFile;\r
+          break;\r
+        }\r
+      }\r
+    }\r
+    ResourceDirectoryEntry++;\r
+  }\r
+  \r
+  return;\r
 }\r
 \r
-int\r
-IsTextShdr(\r
-  Elf_Shdr *Shdr\r
+EFI_IMAGE_OPTIONAL_HEADER_UNION *\r
+GetPeCoffHeader (\r
+  void *Data\r
   )\r
 {\r
-  return (Shdr->sh_flags & (SHF_WRITE | SHF_ALLOC)) == SHF_ALLOC;\r
-}\r
+  EFI_IMAGE_DOS_HEADER             *DosHdr;\r
+  EFI_IMAGE_OPTIONAL_HEADER_UNION  *PeHdr;\r
 \r
-int\r
-IsDataShdr(\r
-  Elf_Shdr *Shdr\r
-  )\r
-{\r
-  return (Shdr->sh_flags & (SHF_WRITE | SHF_ALLOC)) == (SHF_ALLOC | SHF_WRITE);\r
-}\r
+  //\r
+  // Read the dos & pe hdrs of the image\r
+  //\r
+  DosHdr = (EFI_IMAGE_DOS_HEADER *)Data;\r
+  if (DosHdr->e_magic != EFI_IMAGE_DOS_SIGNATURE) {\r
+    // NO DOS header, check for PE/COFF header\r
+    PeHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION *)(Data);\r
+    if (PeHdr->Pe32.Signature != EFI_IMAGE_NT_SIGNATURE) {\r
+      return NULL;\r
+    }\r
+  } else {\r
 \r
-VOID\r
-CreateSectionHeader(\r
-  const CHAR8 *Name,\r
-  UINT32      Offset,\r
-  UINT32      Size,\r
-  UINT32      Flags\r
-  )\r
-{\r
-  EFI_IMAGE_SECTION_HEADER *Hdr;\r
-  Hdr = (EFI_IMAGE_SECTION_HEADER*)(CoffFile + TableOffset);\r
-\r
-  strcpy((char *)Hdr->Name, Name);\r
-  Hdr->Misc.VirtualSize = Size;\r
-  Hdr->VirtualAddress = Offset;\r
-  Hdr->SizeOfRawData = Size;\r
-  Hdr->PointerToRawData = Offset;\r
-  Hdr->PointerToRelocations = 0;\r
-  Hdr->PointerToLinenumbers = 0;\r
-  Hdr->NumberOfRelocations = 0;\r
-  Hdr->NumberOfLinenumbers = 0;\r
-  Hdr->Characteristics = Flags;\r
-\r
-  TableOffset += sizeof (EFI_IMAGE_SECTION_HEADER);\r
+    PeHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION *)(((UINT8 *)Data) + DosHdr->e_lfanew);\r
+    if (PeHdr->Pe32.Signature != EFI_IMAGE_NT_SIGNATURE) {\r
+      return NULL;\r
+    }\r
+  }\r
+  \r
+  return PeHdr;\r
 }\r
 \r
-VOID\r
-ScanSections(\r
-  VOID\r
+void\r
+PeCoffConvertImageToXip (\r
+  UINT8  **FileBuffer,\r
+  UINT32 *FileLength\r
   )\r
 {\r
-  UINT32                          i;\r
-  EFI_IMAGE_DOS_HEADER            *DosHdr;\r
-  EFI_IMAGE_OPTIONAL_HEADER_UNION *NtHdr;\r
-  UINT32                          CoffEntry;\r
-\r
-  CoffEntry = 0;\r
-  CoffOffset = 0;\r
-\r
-  //\r
-  // Coff file start with a DOS header.\r
-  //\r
-  CoffOffset = sizeof(EFI_IMAGE_DOS_HEADER) + 0x40;\r
-  NtHdrOffset = CoffOffset;\r
-  switch (Ehdr->e_machine) {\r
-  case EM_386:\r
-  case EM_ARM:\r
-    CoffOffset += sizeof (EFI_IMAGE_NT_HEADERS32);\r
-       break;\r
-  case EM_X86_64:\r
-  case EM_IA_64:\r
-       CoffOffset += sizeof (EFI_IMAGE_NT_HEADERS64);\r
-       break;\r
-  default:\r
-    VerboseMsg ("%s unknown e_machine type. Assume IA-32", (UINTN)Ehdr->e_machine);\r
-       CoffOffset += sizeof (EFI_IMAGE_NT_HEADERS32);\r
-       break;\r
-  }\r
-\r
-  TableOffset = CoffOffset;\r
-  CoffOffset += CoffNbrSections * sizeof(EFI_IMAGE_SECTION_HEADER);\r
-\r
-  //\r
-  // First text sections.\r
-  //\r
-  CoffOffset = CoffAlign(CoffOffset);\r
-  TextOffset = CoffOffset;\r
-  for (i = 0; i < Ehdr->e_shnum; i++) {\r
-    Elf_Shdr *shdr = GetShdrByIndex(i);\r
-    if (IsTextShdr(shdr)) {\r
-      if ((shdr->sh_addralign != 0) && (shdr->sh_addralign != 1)) {\r
-        // the alignment field is valid\r
-        if ((shdr->sh_addr & (shdr->sh_addralign - 1)) == 0) {\r
-          // if the section address is aligned we must align PE/COFF \r
-          CoffOffset = (CoffOffset + shdr->sh_addralign - 1) & ~(shdr->sh_addralign - 1);\r
-        } else if ((shdr->sh_addr % shdr->sh_addralign) != (CoffOffset % shdr->sh_addralign)) {\r
-          // ARM RVCT tools have behavior outside of the ELF specification to try \r
-          // and make images smaller.  If sh_addr is not aligned to sh_addralign \r
-          // then the section needs to preserve sh_addr MOD sh_addralign. \r
-          // Normally doing nothing here works great.\r
-          Error (NULL, 0, 3000, "Invalid", "Unsupported section alignment.");\r
-        }\r
-      }\r
-      \r
-      /* Relocate entry.  */\r
-      if ((Ehdr->e_entry >= shdr->sh_addr) &&\r
-          (Ehdr->e_entry < shdr->sh_addr + shdr->sh_size)) {\r
-        CoffEntry = CoffOffset + Ehdr->e_entry - shdr->sh_addr;\r
-      }\r
-      CoffSectionsOffset[i] = CoffOffset;\r
-      CoffOffset += shdr->sh_size;\r
-    }\r
+  EFI_IMAGE_OPTIONAL_HEADER_UNION  *PeHdr;\r
+  EFI_IMAGE_OPTIONAL_HEADER_UNION  *NewPeHdr;\r
+  EFI_IMAGE_SECTION_HEADER         *SectionHeader;\r
+  UINTN                            TotalNecessaryFileSize;\r
+  UINTN                            SectionSize;\r
+  UINT8                            *XipFile;\r
+  UINT32                           XipLength;\r
+  UINTN                            Index;\r
+  UINTN                            FirstSectionOffset;\r
+  BOOLEAN                          ConversionNeeded;\r
+\r
+  PeHdr = GetPeCoffHeader ((void *) *FileBuffer);\r
+  if (PeHdr == NULL) {\r
+    return;\r
   }\r
-\r
-  if (Ehdr->e_machine != EM_ARM) {\r
-    CoffOffset = CoffAlign(CoffOffset);\r
+  \r
+  if (PeHdr->Pe32.OptionalHeader.SectionAlignment != PeHdr->Pe32.OptionalHeader.FileAlignment) {\r
+    //\r
+    // The only reason to expand zero fill sections is to make them compatible with XIP images.\r
+    // If SectionAlignment is not equal to FileAlginment then it is not an XIP type image.\r
+    //\r
+    return;\r
   }\r
 \r
   //\r
-  //  Then data sections.\r
+  // Calculate size of XIP file, and determine if the conversion is needed.\r
   //\r
-  DataOffset = CoffOffset;\r
-  for (i = 0; i < Ehdr->e_shnum; i++) {\r
-    Elf_Shdr *shdr = GetShdrByIndex(i);\r
-    if (IsDataShdr(shdr)) {\r
-      if ((shdr->sh_addralign != 0) && (shdr->sh_addralign != 1)) {\r
-        // the alignment field is valid\r
-        if ((shdr->sh_addr & (shdr->sh_addralign - 1)) == 0) {\r
-          // if the section address is aligned we must align PE/COFF \r
-          CoffOffset = (CoffOffset + shdr->sh_addralign - 1) & ~(shdr->sh_addralign - 1);\r
-        } else if ((shdr->sh_addr % shdr->sh_addralign) != (CoffOffset % shdr->sh_addralign)) {\r
-          // ARM RVCT tools have behavior outside of the ELF specification to try \r
-          // and make images smaller.  If sh_addr is not aligned to sh_addralign \r
-          // then the section needs to preserve sh_addr MOD sh_addralign. \r
-          // Normally doing nothing here works great.\r
-          Error (NULL, 0, 3000, "Invalid", "Unsupported section alignment.");\r
-        }\r
+  ConversionNeeded = FALSE;\r
+  XipLength = 0;\r
+  FirstSectionOffset = *FileLength;\r
+  TotalNecessaryFileSize = 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
+    SectionSize = MAX (SectionHeader->Misc.VirtualSize, SectionHeader->SizeOfRawData);\r
+    TotalNecessaryFileSize += SectionSize;\r
+    if (SectionSize > 0) {\r
+      FirstSectionOffset = MIN (FirstSectionOffset, SectionHeader->VirtualAddress);\r
+      XipLength = MAX (XipLength, SectionHeader->VirtualAddress + SectionSize);\r
+      if (SectionHeader->VirtualAddress != SectionHeader->PointerToRawData) {\r
+        ConversionNeeded = TRUE;\r
       }\r
-\r
-      CoffSectionsOffset[i] = CoffOffset;\r
-      CoffOffset += shdr->sh_size;\r
+    }\r
+    if (SectionHeader->Misc.VirtualSize > SectionHeader->SizeOfRawData) {\r
+      ConversionNeeded = TRUE;\r
     }\r
   }\r
-  CoffOffset = CoffAlign(CoffOffset);\r
-\r
-  RelocOffset = CoffOffset;\r
-\r
-  //\r
-  // Allocate base Coff file.  Will be expanded later for relocations.\r
-  //\r
-  CoffFile = (UINT8 *)malloc(CoffOffset);\r
-  memset(CoffFile, 0, CoffOffset);\r
-\r
-  //\r
-  // Fill headers.\r
-  //\r
-  DosHdr = (EFI_IMAGE_DOS_HEADER *)CoffFile;\r
-  DosHdr->e_magic = EFI_IMAGE_DOS_SIGNATURE;\r
-  DosHdr->e_lfanew = NtHdrOffset;\r
-\r
-  NtHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION*)(CoffFile + NtHdrOffset);\r
-\r
-  NtHdr->Pe32.Signature = EFI_IMAGE_NT_SIGNATURE;\r
 \r
-  switch (Ehdr->e_machine) {\r
-  case EM_386:\r
-    NtHdr->Pe32.FileHeader.Machine = EFI_IMAGE_MACHINE_IA32;\r
-    NtHdr->Pe32.OptionalHeader.Magic = EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC;\r
-    break;\r
-  case EM_X86_64:\r
-    NtHdr->Pe32.FileHeader.Machine = EFI_IMAGE_MACHINE_X64;\r
-    NtHdr->Pe32.OptionalHeader.Magic = EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC;\r
-    break;\r
-  case EM_IA_64:\r
-    NtHdr->Pe32.FileHeader.Machine = EFI_IMAGE_MACHINE_IPF;\r
-    NtHdr->Pe32.OptionalHeader.Magic = EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC;\r
-    break;\r
-  case EM_ARM:\r
-    NtHdr->Pe32.FileHeader.Machine = EFI_IMAGE_MACHINE_ARMT;\r
-    NtHdr->Pe32.OptionalHeader.Magic = EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC;\r
-    break;\r
-  default:\r
-    VerboseMsg ("%s unknown e_machine type. Assume IA-32", (UINTN)Ehdr->e_machine);\r
-    NtHdr->Pe32.FileHeader.Machine = EFI_IMAGE_MACHINE_IA32;\r
-    NtHdr->Pe32.OptionalHeader.Magic = EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC;\r
+  if (FirstSectionOffset < PeHdr->Pe32.OptionalHeader.SizeOfHeaders) {\r
+    //\r
+    // If one of the sections should be loaded to an offset overlapping with\r
+    // the executable header, then it cannot be made into an XIP image.\r
+    //\r
+    VerboseMsg ("PE/COFF conversion to XIP is impossible due to overlap");\r
+    VerboseMsg ("of section data with the executable header.");\r
+    return;\r
   }\r
 \r
-  NtHdr->Pe32.FileHeader.NumberOfSections = CoffNbrSections;\r
-  NtHdr->Pe32.FileHeader.TimeDateStamp = time(NULL);\r
-  NtHdr->Pe32.FileHeader.PointerToSymbolTable = 0;\r
-  NtHdr->Pe32.FileHeader.NumberOfSymbols = 0;\r
-  NtHdr->Pe32.FileHeader.SizeOfOptionalHeader = sizeof(NtHdr->Pe32.OptionalHeader);\r
-  NtHdr->Pe32.FileHeader.Characteristics = EFI_IMAGE_FILE_EXECUTABLE_IMAGE\r
-    | EFI_IMAGE_FILE_LINE_NUMS_STRIPPED\r
-    | EFI_IMAGE_FILE_LOCAL_SYMS_STRIPPED\r
-    | EFI_IMAGE_FILE_32BIT_MACHINE;\r
+  if (FirstSectionOffset == *FileLength) {\r
+    //\r
+    // If we never found a section with a non-zero size, then we\r
+    // skip the conversion.\r
+    //\r
+    return;\r
+  }\r
 \r
-  NtHdr->Pe32.OptionalHeader.SizeOfCode = DataOffset - TextOffset;\r
-  NtHdr->Pe32.OptionalHeader.SizeOfInitializedData = RelocOffset - DataOffset;\r
-  NtHdr->Pe32.OptionalHeader.SizeOfUninitializedData = 0;\r
-  NtHdr->Pe32.OptionalHeader.AddressOfEntryPoint = CoffEntry;\r
+  TotalNecessaryFileSize += FirstSectionOffset;\r
 \r
-  NtHdr->Pe32.OptionalHeader.BaseOfCode = TextOffset;\r
+  if (!ConversionNeeded) {\r
+    return;\r
+  }\r
 \r
-  NtHdr->Pe32.OptionalHeader.BaseOfData = DataOffset;\r
-  NtHdr->Pe32.OptionalHeader.ImageBase = 0;\r
-  NtHdr->Pe32.OptionalHeader.SectionAlignment = CoffAlignment;\r
-  NtHdr->Pe32.OptionalHeader.FileAlignment = CoffAlignment;\r
-  NtHdr->Pe32.OptionalHeader.SizeOfImage = 0;\r
+  if (XipLength > (2 * TotalNecessaryFileSize)) {\r
+    VerboseMsg ("PE/COFF conversion to XIP appears to be larger than necessary.");\r
+    VerboseMsg ("The image linking process may have left unused memory ranges.");\r
+  }\r
 \r
-  NtHdr->Pe32.OptionalHeader.SizeOfHeaders = TextOffset;\r
-  NtHdr->Pe32.OptionalHeader.NumberOfRvaAndSizes = EFI_IMAGE_NUMBER_OF_DIRECTORY_ENTRIES;\r
+  if (PeHdr->Pe32.FileHeader.PointerToSymbolTable != 0) {\r
+    //\r
+    // This field is obsolete and should be zero\r
+    //\r
+    PeHdr->Pe32.FileHeader.PointerToSymbolTable = 0;\r
+  }\r
 \r
   //\r
-  // Section headers.\r
+  // Allocate the extra space that we need to grow the image\r
   //\r
-  if ((DataOffset - TextOffset) > 0) {\r
-    CreateSectionHeader (".text", TextOffset, DataOffset - TextOffset,\r
-            EFI_IMAGE_SCN_CNT_CODE\r
-            | EFI_IMAGE_SCN_MEM_EXECUTE\r
-            | EFI_IMAGE_SCN_MEM_READ);\r
-  } else {\r
-    // Don't make a section of size 0. \r
-    NtHdr->Pe32.FileHeader.NumberOfSections--;\r
+  XipFile = malloc (XipLength);\r
+  if (XipFile == NULL) {\r
+    Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!");\r
+    return;\r
   }\r
+  memset (XipFile, 0, XipLength);\r
 \r
-  if ((RelocOffset - TextOffset) > 0) {\r
-    CreateSectionHeader (".data", DataOffset, RelocOffset - DataOffset,\r
-            EFI_IMAGE_SCN_CNT_INITIALIZED_DATA\r
-            | EFI_IMAGE_SCN_MEM_WRITE\r
-            | EFI_IMAGE_SCN_MEM_READ);\r
-  } else {\r
-    // Don't make a section of size 0. \r
-    NtHdr->Pe32.FileHeader.NumberOfSections--;\r
-  }\r
-}\r
+  //\r
+  // Copy the file headers\r
+  //\r
+  memcpy (XipFile, *FileBuffer, PeHdr->Pe32.OptionalHeader.SizeOfHeaders);\r
 \r
-VOID\r
-WriteSections(\r
-  int   (*Filter)(Elf_Shdr *)\r
-  )\r
-{\r
-  UINT32      Idx;\r
-  Elf_Shdr  *SecShdr;\r
-  UINT32      SecOffset;\r
-\r
-  //\r
-  // First: copy sections.\r
-  //\r
-  for (Idx = 0; Idx < Ehdr->e_shnum; Idx++) {\r
-    Elf_Shdr *Shdr = GetShdrByIndex(Idx);\r
-    if ((*Filter)(Shdr)) {\r
-      switch (Shdr->sh_type) {\r
-      case SHT_PROGBITS:\r
-        /* Copy.  */\r
-        memcpy(CoffFile + CoffSectionsOffset[Idx],\r
-              (UINT8*)Ehdr + Shdr->sh_offset,\r
-              Shdr->sh_size);\r
-        break;\r
-      \r
-      case SHT_NOBITS:\r
-        memset(CoffFile + CoffSectionsOffset[Idx], 0, Shdr->sh_size);\r
-        break;\r
-      \r
-      default:\r
-        //\r
-        //  Ignore for unkown section type.\r
-        //\r
-        VerboseMsg ("%s unknown section type %x. We directly copy this section into Coff file", mInImageName, (UINTN)Shdr->sh_type);\r
-        break;\r
-      }\r
-    }\r
+  NewPeHdr = GetPeCoffHeader ((void *)XipFile);\r
+  if (NewPeHdr == NULL) {\r
+    free (XipFile);\r
+    return;\r
   }\r
 \r
   //\r
-  // Second: apply relocations.\r
+  // Copy the section data over to the appropriate XIP offsets\r
   //\r
-  for (Idx = 0; Idx < Ehdr->e_shnum; Idx++) {\r
-    Elf_Shdr *RelShdr = GetShdrByIndex(Idx);\r
-    if (RelShdr->sh_type != SHT_REL)\r
-      continue;\r
-    SecShdr = GetShdrByIndex(RelShdr->sh_info);\r
-    SecOffset = CoffSectionsOffset[RelShdr->sh_info];\r
-    if (RelShdr->sh_type == SHT_REL && (*Filter)(SecShdr)) {\r
-      UINT32 RelIdx;\r
-      Elf_Shdr *SymtabShdr = GetShdrByIndex(RelShdr->sh_link);\r
-      UINT8 *Symtab = (UINT8*)Ehdr + SymtabShdr->sh_offset;\r
-\r
-      for (RelIdx = 0; RelIdx < RelShdr->sh_size; RelIdx += RelShdr->sh_entsize) {\r
-        Elf_Rel *Rel = (Elf_Rel *)((UINT8*)Ehdr + RelShdr->sh_offset + RelIdx);\r
-        Elf_Sym *Sym = (Elf_Sym *)(Symtab + ELF_R_SYM(Rel->r_info) * SymtabShdr->sh_entsize);\r
-        Elf_Shdr *SymShdr;\r
-        UINT8 *Targ;\r
-\r
-        if (Sym->st_shndx == SHN_UNDEF\r
-            || Sym->st_shndx == SHN_ABS\r
-            || Sym->st_shndx > Ehdr->e_shnum) {\r
-          Error (NULL, 0, 3000, "Invalid", "%s bad symbol definition.", mInImageName);\r
-        }\r
-        SymShdr = GetShdrByIndex(Sym->st_shndx);\r
-\r
-        //\r
-        // Note: r_offset in a memory address.\r
-        //  Convert it to a pointer in the coff file.\r
-        //\r
-        Targ = CoffFile + SecOffset + (Rel->r_offset - SecShdr->sh_addr);\r
-\r
-        if (Ehdr->e_machine == EM_386) {\r
-          switch (ELF_R_TYPE(Rel->r_info)) {\r
-          case R_386_NONE:\r
-            break;\r
-          case R_386_32:\r
-            //\r
-            // Absolute relocation.\r
-            //\r
-            *(UINT32 *)Targ = *(UINT32 *)Targ - SymShdr->sh_addr\r
-              + CoffSectionsOffset[Sym->st_shndx];\r
-            break;\r
-          case R_386_PC32:\r
-            //\r
-            // Relative relocation: Symbol - Ip + Addend\r
-            //\r
-            *(UINT32 *)Targ = *(UINT32 *)Targ\r
-              + (CoffSectionsOffset[Sym->st_shndx] - SymShdr->sh_addr)\r
-              - (SecOffset - SecShdr->sh_addr);\r
-            break;\r
-          default:\r
-            Error (NULL, 0, 3000, "Invalid", "%s unhandled section type %x.", mInImageName, ELF_R_TYPE(Rel->r_info));\r
-          }\r
-        } else if (Ehdr->e_machine == EM_ARM) {\r
-          switch (ELF32_R_TYPE(Rel->r_info)) {\r
-          case R_ARM_RBASE:   // No relocation - no action required\r
-          case R_ARM_PC24:    // PC-relative relocations don't require modification\r
-          case R_ARM_XPC25:   // PC-relative relocations don't require modification\r
-            break;\r
-          case R_ARM_ABS32:\r
-          case R_ARM_RABS32:\r
-            //\r
-            // Absolute relocation.\r
-            //\r
-            *(UINT32 *)Targ = *(UINT32 *)Targ - SymShdr->sh_addr + CoffSectionsOffset[Sym->st_shndx];\r
-            break;\r
-          default:\r
-            Error (NULL, 0, 3000, "Invalid", "%s unhandled section type %x.", mInImageName, ELF32_R_TYPE(Rel->r_info));\r
-          }\r
-        }\r
-      }\r
+  SectionHeader = (EFI_IMAGE_SECTION_HEADER *) ((UINT8 *) &(NewPeHdr->Pe32.OptionalHeader) + NewPeHdr->Pe32.FileHeader.SizeOfOptionalHeader);\r
+  for (Index = 0; Index < PeHdr->Pe32.FileHeader.NumberOfSections; Index ++, SectionHeader ++) {\r
+    if (SectionHeader->SizeOfRawData > 0) {\r
+      memcpy (\r
+        XipFile + SectionHeader->VirtualAddress,\r
+        *FileBuffer + SectionHeader->PointerToRawData,\r
+        SectionHeader->SizeOfRawData\r
+        );\r
     }\r
+    //\r
+    // Make the size of raw data in section header alignment.\r
+    //\r
+    SectionHeader->SizeOfRawData = (SectionHeader->Misc.VirtualSize + PeHdr->Pe32.OptionalHeader.FileAlignment - 1) & (~(PeHdr->Pe32.OptionalHeader.FileAlignment - 1));\r
+    SectionHeader->PointerToRawData = SectionHeader->VirtualAddress;\r
   }\r
-}\r
 \r
-VOID\r
-CoffAddFixupEntry(\r
-  UINT16 Val\r
-  )\r
-{\r
-  *CoffEntryRel = Val;\r
-  CoffEntryRel++;\r
-  CoffBaseRel->SizeOfBlock += 2;\r
-  CoffOffset += 2;\r
+  free (*FileBuffer);\r
+  *FileLength = XipLength;\r
+  *FileBuffer = XipFile;\r
 }\r
 \r
-VOID\r
-CoffAddFixup(\r
-  UINT32 Offset,\r
-  UINT8  Type\r
+UINT8 *\r
+CreateHiiResouceSectionHeader (\r
+  UINT32 *pSectionHeaderSize, \r
+  UINT32 HiiDataSize\r
   )\r
-{\r
-  if (CoffBaseRel == NULL\r
-      || CoffBaseRel->VirtualAddress != (Offset & ~0xfff)) {\r
-    if (CoffBaseRel != NULL) {\r
-      //\r
-      // Add a null entry (is it required ?)\r
-      //\r
-      CoffAddFixupEntry (0);\r
-      //\r
-      // Pad for alignment.\r
-      //\r
-      if (CoffOffset % 4 != 0)\r
-        CoffAddFixupEntry (0);\r
-    }\r
+/*++\r
 \r
-    CoffFile = realloc\r
-      (CoffFile,\r
-       CoffOffset + sizeof(EFI_IMAGE_BASE_RELOCATION) + 2*0x1000);\r
-    memset(CoffFile + CoffOffset, 0,\r
-     sizeof(EFI_IMAGE_BASE_RELOCATION) + 2*0x1000);\r
+Routine Description:\r
 \r
-    CoffBaseRel = (EFI_IMAGE_BASE_RELOCATION*)(CoffFile + CoffOffset);\r
-    CoffBaseRel->VirtualAddress = Offset & ~0xfff;\r
-    CoffBaseRel->SizeOfBlock = sizeof(EFI_IMAGE_BASE_RELOCATION);\r
+  Create COFF resource section header\r
 \r
-    CoffEntryRel = (UINT16 *)(CoffBaseRel + 1);\r
-    CoffOffset += sizeof(EFI_IMAGE_BASE_RELOCATION);\r
-  }\r
+Arguments:\r
 \r
-  //\r
-  // Fill the entry.\r
-  //\r
-  CoffAddFixupEntry((Type << 12) | (Offset & 0xfff));\r
-}\r
+  pSectionHeaderSize - Pointer to section header size.\r
+  HiiDataSize        - Size of the total HII data in section.\r
 \r
+Returns:\r
+  The created section header buffer.\r
 \r
-Elf_Phdr *\r
-GetPhdrByIndex (\r
-  UINT32 num\r
-  )\r
+--*/\r
 {\r
-  if (num >= Ehdr->e_phnum) {\r
+  UINT32  HiiSectionHeaderSize;\r
+  UINT32  HiiSectionOffset;\r
+  UINT8   *HiiSectionHeader;\r
+  EFI_IMAGE_RESOURCE_DIRECTORY        *ResourceDirectory;\r
+  EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY  *TypeResourceDirectoryEntry;\r
+  EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY  *NameResourceDirectoryEntry;\r
+  EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY  *LanguageResourceDirectoryEntry;\r
+  EFI_IMAGE_RESOURCE_DIRECTORY_STRING *ResourceDirectoryString;\r
+  EFI_IMAGE_RESOURCE_DATA_ENTRY       *ResourceDataEntry;\r
+\r
+  //\r
+  // Calculate the total size for the resource header (include Type, Name and Language)\r
+  // then allocate memory for the resource header.\r
+  //\r
+  HiiSectionHeaderSize = 3 * (sizeof (EFI_IMAGE_RESOURCE_DIRECTORY) + sizeof (EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY)) \r
+                          + 3 * (sizeof (UINT16) + 3 * sizeof (CHAR16)) \r
+                          + sizeof (EFI_IMAGE_RESOURCE_DATA_ENTRY);\r
+  HiiSectionHeader = malloc (HiiSectionHeaderSize);\r
+  if (HiiSectionHeader == NULL) {\r
+    Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!");\r
     return NULL;\r
   }\r
-  \r
-  return (Elf32_Phdr *)((UINT8*)gPhdrBase + num * Ehdr->e_phentsize);\r
+  memset (HiiSectionHeader, 0, HiiSectionHeaderSize);\r
+\r
+  HiiSectionOffset = 0;\r
+  //\r
+  // Create Type entry \r
+  //\r
+  ResourceDirectory = (EFI_IMAGE_RESOURCE_DIRECTORY *) (HiiSectionHeader + HiiSectionOffset);\r
+  HiiSectionOffset += sizeof (EFI_IMAGE_RESOURCE_DIRECTORY);\r
+  ResourceDirectory->NumberOfNamedEntries = 1;\r
+  TypeResourceDirectoryEntry = (EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY *) (HiiSectionHeader + HiiSectionOffset);\r
+  HiiSectionOffset += sizeof (EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY);\r
+  TypeResourceDirectoryEntry->u1.s.NameIsString      = 1;\r
+  TypeResourceDirectoryEntry->u2.s.DataIsDirectory   = 1;\r
+  TypeResourceDirectoryEntry->u2.s.OffsetToDirectory = HiiSectionOffset;\r
+  //\r
+  // Create Name entry\r
+  //\r
+  ResourceDirectory = (EFI_IMAGE_RESOURCE_DIRECTORY *) (HiiSectionHeader + HiiSectionOffset);\r
+  HiiSectionOffset += sizeof (EFI_IMAGE_RESOURCE_DIRECTORY);\r
+  ResourceDirectory->NumberOfNamedEntries = 1;\r
+  NameResourceDirectoryEntry = (EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY *) (HiiSectionHeader + HiiSectionOffset);\r
+  HiiSectionOffset += sizeof (EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY);\r
+  NameResourceDirectoryEntry->u1.s.NameIsString      = 1;\r
+  NameResourceDirectoryEntry->u2.s.DataIsDirectory   = 1;\r
+  NameResourceDirectoryEntry->u2.s.OffsetToDirectory = HiiSectionOffset;\r
+  //\r
+  // Create Language entry\r
+  //\r
+  ResourceDirectory = (EFI_IMAGE_RESOURCE_DIRECTORY *) (HiiSectionHeader + HiiSectionOffset);\r
+  HiiSectionOffset += sizeof (EFI_IMAGE_RESOURCE_DIRECTORY);\r
+  ResourceDirectory->NumberOfNamedEntries = 1;\r
+  LanguageResourceDirectoryEntry = (EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY *) (HiiSectionHeader + HiiSectionOffset);\r
+  HiiSectionOffset += sizeof (EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY);\r
+  LanguageResourceDirectoryEntry->u1.s.NameIsString = 1;\r
+  //\r
+  // Create string entry for Type\r
+  //\r
+  TypeResourceDirectoryEntry->u1.s.NameOffset = HiiSectionOffset;\r
+  ResourceDirectoryString = (EFI_IMAGE_RESOURCE_DIRECTORY_STRING *) (HiiSectionHeader + HiiSectionOffset);\r
+  ResourceDirectoryString->Length = 3;\r
+  ResourceDirectoryString->String[0] = L'H';\r
+  ResourceDirectoryString->String[1] = L'I';\r
+  ResourceDirectoryString->String[2] = L'I';\r
+  HiiSectionOffset = HiiSectionOffset + sizeof (ResourceDirectoryString->Length) + ResourceDirectoryString->Length * sizeof (ResourceDirectoryString->String[0]);\r
+  //\r
+  // Create string entry for Name\r
+  //\r
+  NameResourceDirectoryEntry->u1.s.NameOffset = HiiSectionOffset;\r
+  ResourceDirectoryString = (EFI_IMAGE_RESOURCE_DIRECTORY_STRING *) (HiiSectionHeader + HiiSectionOffset);\r
+  ResourceDirectoryString->Length = 3;\r
+  ResourceDirectoryString->String[0] = L'E';\r
+  ResourceDirectoryString->String[1] = L'F';\r
+  ResourceDirectoryString->String[2] = L'I';\r
+  HiiSectionOffset = HiiSectionOffset + sizeof (ResourceDirectoryString->Length) + ResourceDirectoryString->Length * sizeof (ResourceDirectoryString->String[0]);\r
+  //\r
+  // Create string entry for Language\r
+  //\r
+  LanguageResourceDirectoryEntry->u1.s.NameOffset = HiiSectionOffset;\r
+  ResourceDirectoryString = (EFI_IMAGE_RESOURCE_DIRECTORY_STRING *) (HiiSectionHeader + HiiSectionOffset);\r
+  ResourceDirectoryString->Length = 3;\r
+  ResourceDirectoryString->String[0] = L'B';\r
+  ResourceDirectoryString->String[1] = L'I';\r
+  ResourceDirectoryString->String[2] = L'N';\r
+  HiiSectionOffset = HiiSectionOffset + sizeof (ResourceDirectoryString->Length) + ResourceDirectoryString->Length * sizeof (ResourceDirectoryString->String[0]);\r
+  //\r
+  // Create Leaf data\r
+  //\r
+  LanguageResourceDirectoryEntry->u2.OffsetToData = HiiSectionOffset;\r
+  ResourceDataEntry = (EFI_IMAGE_RESOURCE_DATA_ENTRY *) (HiiSectionHeader + HiiSectionOffset);\r
+  HiiSectionOffset += sizeof (EFI_IMAGE_RESOURCE_DATA_ENTRY);\r
+  ResourceDataEntry->OffsetToData = HiiSectionOffset;\r
+  ResourceDataEntry->Size = HiiDataSize;\r
+\r
+  *pSectionHeaderSize = HiiSectionHeaderSize;\r
+  return HiiSectionHeader;\r
 }\r
 \r
-\r
-VOID\r
-WriteRelocations(\r
-  VOID\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
-  UINT32                           Index;\r
-  EFI_IMAGE_OPTIONAL_HEADER_UNION  *NtHdr;\r
-  EFI_IMAGE_DATA_DIRECTORY         *Dir;\r
-  BOOLEAN                          FoundRelocations;\r
-  Elf_Dyn                          *Dyn;\r
-  Elf_Rel                          *Rel;\r
-  UINTN                            RelElementSize;\r
-  UINTN                            RelSize;\r
-  UINTN                            RelOffset;\r
-  UINTN                            K;\r
-  UINT8                            *Targ;\r
-  Elf32_Phdr                       *DynamicSegment;\r
-  Elf32_Phdr                       *TargetSegment;\r
-\r
-  for (Index = 0, FoundRelocations = FALSE; Index < Ehdr->e_shnum; Index++) {\r
-    Elf_Shdr *RelShdr = GetShdrByIndex(Index);\r
-    if (RelShdr->sh_type == SHT_REL) {\r
-      Elf_Shdr *SecShdr = GetShdrByIndex(RelShdr->sh_info);\r
-      if (IsTextShdr(SecShdr) || IsDataShdr(SecShdr)) {\r
-        UINT32 RelIdx;\r
-        FoundRelocations = TRUE;\r
-        for (RelIdx = 0; RelIdx < RelShdr->sh_size; RelIdx += RelShdr->sh_entsize) {\r
-          Elf_Rel *Rel = (Elf_Rel *)\r
-            ((UINT8*)Ehdr + RelShdr->sh_offset + RelIdx);\r
-          \r
-          if (Ehdr->e_machine == EM_386) { \r
-            switch (ELF_R_TYPE(Rel->r_info)) {\r
-            case R_386_NONE:\r
-            case R_386_PC32:\r
-              break;\r
-            case R_386_32:\r
-              CoffAddFixup(CoffSectionsOffset[RelShdr->sh_info]\r
-              + (Rel->r_offset - SecShdr->sh_addr),\r
-              EFI_IMAGE_REL_BASED_HIGHLOW);\r
-              break;\r
-            default:\r
-              Error (NULL, 0, 3000, "Invalid", "%s unhandled section type %x.", mInImageName, ELF_R_TYPE(Rel->r_info));\r
-            }\r
-          } else if (Ehdr->e_machine == EM_ARM) {\r
-            switch (ELF32_R_TYPE(Rel->r_info)) {\r
-            case R_ARM_RBASE:\r
-            case R_ARM_PC24:\r
-            case R_ARM_XPC25:\r
-              break;\r
-            case R_ARM_ABS32:\r
-            case R_ARM_RABS32:\r
-              CoffAddFixup (\r
-                CoffSectionsOffset[RelShdr->sh_info]\r
-                + (Rel->r_offset - SecShdr->sh_addr),\r
-                EFI_IMAGE_REL_BASED_HIGHLOW\r
-                );\r
-              break;\r
-            default:\r
-              Error (NULL, 0, 3000, "Invalid", "%s unhandled section type %x.", mInImageName, ELF32_R_TYPE(Rel->r_info));\r
-            }\r
-          } else {\r
-            Error (NULL, 0, 3000, "Not Supported", "This tool does not support relocations for ELF with e_machine %d (processor type).", Ehdr->e_machine);\r
-          }\r
-        }\r
-      }\r
-    }\r
-  }\r
-\r
-  if (!FoundRelocations && (Ehdr->e_machine == EM_ARM)) {\r
-    /* Try again, but look for PT_DYNAMIC instead of SHT_REL */\r
-\r
-    for (Index = 0; Index < Ehdr->e_phnum; Index++) {\r
-      RelElementSize = 0;\r
-      RelSize = 0;\r
-      RelOffset = 0;\r
-\r
-      DynamicSegment = GetPhdrByIndex (Index);\r
-\r
-      if (DynamicSegment->p_type == PT_DYNAMIC) {\r
-        Dyn = (Elf32_Dyn *) ((UINT8 *)Ehdr + DynamicSegment->p_offset);\r
-\r
-        while (Dyn->d_tag != DT_NULL) {\r
-          switch (Dyn->d_tag) {\r
-            case  DT_REL:\r
-              RelOffset = Dyn->d_un.d_val;\r
-              break;\r
-\r
-            case  DT_RELSZ:\r
-              RelSize = Dyn->d_un.d_val;\r
-              break;\r
-\r
-            case  DT_RELENT:\r
-              RelElementSize = Dyn->d_un.d_val;\r
-              break;\r
-          }\r
-          Dyn++;\r
-        }\r
-        if (( RelOffset == 0 ) || ( RelSize == 0 ) || ( RelElementSize == 0 )) {\r
-          Error (NULL, 0, 3000, "Invalid", "%s bad ARM dynamic relocations.", mInImageName);\r
-        }\r
-\r
-        for (K = 0; K < RelSize; K += RelElementSize) {\r
+/*++\r
 \r
-          Rel = (Elf32_Rel *) ((UINT8 *) Ehdr + DynamicSegment->p_offset + RelOffset + K);\r
+Routine Description:\r
 \r
-          switch (ELF32_R_TYPE (Rel->r_info)) {\r
-          case  R_ARM_RBASE:\r
-            break;\r
-          case  R_ARM_RABS32:\r
-            TargetSegment = GetPhdrByIndex (ELF32_R_SYM (Rel->r_info) - 1);\r
+  Support routine for the PE/COFF Loader that reads a buffer from a PE/COFF file\r
 \r
-            // Note: r_offset in a memory address.  Convert it to a pointer in the coff file.\r
-            Targ = CoffFile + CoffSectionsOffset[ ELF32_R_SYM( Rel->r_info ) ] + Rel->r_offset - TargetSegment->p_vaddr;\r
+Arguments:\r
 \r
-            *(UINT32 *)Targ = *(UINT32 *)Targ + CoffSectionsOffset [ELF32_R_SYM( Rel->r_info )];\r
+  FileHandle - The handle to the PE/COFF file\r
 \r
-            CoffAddFixup (CoffSectionsOffset[ELF32_R_SYM (Rel->r_info)] + (Rel->r_offset - TargetSegment->p_vaddr), EFI_IMAGE_REL_BASED_HIGHLOW);\r
-            break;\r
-          default:\r
-            Error (NULL, 0, 3000, "Invalid", "%s bad ARM dynamic relocations, unkown type.", mInImageName);\r
-          }\r
-        }\r
-        break;\r
-      }\r
-    }\r
-  }\r
-\r
-  //\r
-  // Pad by adding empty entries.\r
-  //\r
-  while (CoffOffset & (CoffAlignment - 1)) {\r
-    CoffAddFixupEntry(0);\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
-  NtHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION *)(CoffFile + NtHdrOffset);\r
-  Dir = &NtHdr->Pe32.OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC];\r
-  Dir->Size = CoffOffset - RelocOffset;\r
-  if (Dir->Size == 0) {\r
-    // If no relocations, null out the directory entry and don't add the .reloc section\r
-    Dir->VirtualAddress = 0;\r
-    NtHdr->Pe32.FileHeader.NumberOfSections--;\r
-  } else {\r
-    Dir->VirtualAddress = RelocOffset;\r
-    CreateSectionHeader (".reloc", RelocOffset, CoffOffset - RelocOffset,\r
-            EFI_IMAGE_SCN_CNT_INITIALIZED_DATA\r
-            | EFI_IMAGE_SCN_MEM_DISCARDABLE\r
-            | EFI_IMAGE_SCN_MEM_READ);\r
-  }\r
+  Buffer     - A pointer to the buffer to read the data into.\r
 \r
-}\r
+Returns:\r
 \r
-VOID\r
-WriteDebug(\r
-  VOID\r
-  )\r
+  EFI_SUCCESS - ReadSize bytes of data were read into Buffer from the PE/COFF file starting at FileOffset\r
+\r
+--*/\r
 {\r
-  UINT32                              Len;\r
-  UINT32                              DebugOffset;\r
-  EFI_IMAGE_OPTIONAL_HEADER_UNION     *NtHdr;\r
-  EFI_IMAGE_DATA_DIRECTORY            *DataDir;\r
-  EFI_IMAGE_DEBUG_DIRECTORY_ENTRY     *Dir;\r
-  EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY *Nb10;\r
-\r
-  Len = strlen(mInImageName) + 1;\r
-  DebugOffset = CoffOffset;\r
-\r
-  CoffOffset += sizeof(EFI_IMAGE_DEBUG_DIRECTORY_ENTRY)\r
-    + sizeof(EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY)\r
-    + Len;\r
-  CoffOffset = CoffAlign(CoffOffset);\r
-\r
-  CoffFile = realloc(CoffFile, CoffOffset);\r
-  memset(CoffFile + DebugOffset, 0, CoffOffset - DebugOffset);\r
-\r
-  Dir = (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY*)(CoffFile + DebugOffset);\r
-  Dir->Type = EFI_IMAGE_DEBUG_TYPE_CODEVIEW;\r
-  Dir->SizeOfData = sizeof(EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY) + Len;\r
-  Dir->RVA = DebugOffset + sizeof(EFI_IMAGE_DEBUG_DIRECTORY_ENTRY);\r
-  Dir->FileOffset = DebugOffset + sizeof(EFI_IMAGE_DEBUG_DIRECTORY_ENTRY);\r
-\r
-  Nb10 = (EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY*)(Dir + 1);\r
-  Nb10->Signature = CODEVIEW_SIGNATURE_NB10;\r
-  strcpy ((char *)(Nb10 + 1), mInImageName);\r
-\r
-\r
-  NtHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION *)(CoffFile + NtHdrOffset);\r
-  DataDir = &NtHdr->Pe32.OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG];\r
-  DataDir->VirtualAddress = DebugOffset;\r
-  DataDir->Size = CoffOffset - DebugOffset;\r
-  if (DataDir->Size == 0) {\r
-    // If no debug, null out the directory entry and don't add the .debug section\r
-    DataDir->VirtualAddress = 0;\r
-    NtHdr->Pe32.FileHeader.NumberOfSections--;\r
-  } else {\r
-    DataDir->VirtualAddress = DebugOffset;\r
-    CreateSectionHeader (".debug", DebugOffset, CoffOffset - DebugOffset,\r
-            EFI_IMAGE_SCN_CNT_INITIALIZED_DATA\r
-            | EFI_IMAGE_SCN_MEM_DISCARDABLE\r
-            | EFI_IMAGE_SCN_MEM_READ);\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
-VOID\r
-ConvertElf (\r
-  UINT8  **FileBuffer,\r
-  UINT32 *FileLength\r
+EFI_STATUS\r
+SetAddressToSectionHeader (\r
+  IN     CHAR8   *FileName,\r
+  IN OUT UINT8   *FileBuffer,\r
+  IN     UINT64  NewPe32BaseAddress\r
   )\r
-{\r
-  EFI_IMAGE_OPTIONAL_HEADER_UNION *NtHdr;\r
+/*++\r
 \r
-  //\r
-  // Check header, read section table.\r
-  //\r
-  Ehdr = (Elf32_Ehdr*)*FileBuffer;\r
-  if (!CheckElfHeader())\r
-    return;\r
+Routine Description:\r
 \r
-  VerboseMsg ("Check Efl Image Header");\r
-  //\r
-  // Compute sections new address.\r
-  //\r
-  \r
-  ScanSections();\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
-  VerboseMsg ("Compute sections new address.");\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
-  // Write and relocate sections.\r
+  // Initialize context\r
   //\r
-  WriteSections(IsTextShdr);\r
-  WriteSections(IsDataShdr);\r
-  VerboseMsg ("Write and relocate sections.");\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
-  // Translate and write relocations.\r
+  // Get PeHeader pointer\r
   //\r
-  WriteRelocations();\r
-  VerboseMsg ("Translate and write relocations.");\r
+  ImgHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION *)(FileBuffer + ImageContext.PeCoffHeaderOffset);\r
 \r
   //\r
-  // Write debug info.\r
+  // Get section header list\r
   //\r
-  WriteDebug();\r
-  VerboseMsg ("Write debug info.");\r
-\r
-  NtHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION *)(CoffFile + NtHdrOffset);\r
-  NtHdr->Pe32.OptionalHeader.SizeOfImage = CoffOffset;\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
-  // Replace.\r
+  // Set base address into the first section header that doesn't point to code section.\r
   //\r
-  free(*FileBuffer);\r
-  *FileBuffer = CoffFile;\r
-  *FileLength = CoffOffset;\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
-  // Free memory space\r
+  // BaseAddress is set to section header.\r
   //\r
-  if (CoffSectionsOffset != NULL) {\r
-    free (CoffSectionsOffset);\r
-  }\r
+  return EFI_SUCCESS;\r
 }\r
 \r
-void\r
-ZeroXdataSection (\r
- IN     CHAR8                 *ImageName,\r
- IN OUT UINT8                 *FileBuffer,\r
- IN EFI_IMAGE_SECTION_HEADER  *SectionHeader,\r
- IN     UINT32                 SectionTotalNumber\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
-  FILE   *fpMapFile;\r
-  CHAR8  MapFileName[_MAX_PATH];\r
-  CHAR8  Line [MAX_LINE_LEN];\r
-  CHAR8  KeyWord [MAX_LINE_LEN];\r
-  CHAR8  SectionName [MAX_LINE_LEN];\r
-  UINT32 FunctionType = 0;\r
-  UINT32 SectionOffset;\r
-  UINT32 SectionLength;\r
-  UINT32 SectionNumber;\r
-  CHAR8  *PdbPointer;\r
-  INT32  Index = 0;\r
-\r
-  for (Index = 0; Index < SectionTotalNumber; Index ++) {\r
-    if (stricmp ((char *)SectionHeader[Index].Name, ".zdata") == 0) {\r
-      //\r
-      // try to zero the customized .zdata section, which is mapped to .xdata\r
-      //\r
-      memset (FileBuffer + SectionHeader[Index].PointerToRawData, 0, SectionHeader[Index].SizeOfRawData);\r
-      DebugMsg (NULL, 0, 9, NULL, "Zero the .xdata section for PE image at Offset 0x%x and Length 0x%x", SectionHeader[Index].PointerToRawData, SectionHeader[Index].SizeOfRawData);\r
-      return;\r
-    }\r
-  }\r
-  //\r
-  // Try to get PDB file name\r
-  //\r
-  PdbPointer = (CHAR8  *) PeCoffLoaderGetPdbPointer (FileBuffer);\r
-  if (PdbPointer != NULL) {\r
-    strcpy (MapFileName, PdbPointer);\r
-  } else {\r
-    strcpy (MapFileName, ImageName);\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
-  // Construct map file name\r
+  // Initialize context\r
   //\r
-  Index = strlen (MapFileName) - 1;\r
-  while (Index >= 0 && MapFileName[Index] != '.') {\r
-    Index --;\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
-  if (Index < 0) {\r
-    //\r
-    // don't know how to costruct map file\r
-    //\r
-    return;\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
-  // fill map file postfix\r
+  // Get PeHeader pointer\r
   //\r
-  MapFileName[Index + 1] = 'm';\r
-  MapFileName[Index + 2] = 'a';\r
-  MapFileName[Index + 3] = 'p';\r
-  MapFileName[Index + 4] = '\0';\r
+  ImgHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION *)(FileBuffer + ImageContext.PeCoffHeaderOffset);\r
 \r
   //\r
-  // try opening Map File\r
+  // Load and Relocate Image Data\r
   //\r
-  fpMapFile = fopen (MapFileName, "r");\r
-  if (fpMapFile == NULL) {\r
-    //\r
-    // Can't open Map file. Maybe it doesn't exist.\r
-    //\r
-    return;\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
-  // Output Functions information into Fv Map file\r
+  // Copy Relocated data to raw image file.\r
   //\r
-  while (fgets (Line, MAX_LINE_LEN, fpMapFile) != NULL) {\r
-    //\r
-    // Skip blank line\r
-    //\r
-    if (Line[0] == 0x0a) {\r
-      if (FunctionType != 0) {\r
-        //\r
-        // read all section table data\r
-        //\r
-        FunctionType = 0;\r
-        break;\r
-      }\r
-      FunctionType = 0;\r
-      continue;\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
-    // By Start keyword\r
-    //\r
-    if (FunctionType == 0) {\r
-      sscanf (Line, "%s", KeyWord);\r
-      if (stricmp (KeyWord, "Start") == 0) {\r
-        //\r
-        // function list\r
-        //\r
-        FunctionType = 1;\r
-      }\r
-      continue;\r
-    }\r
-    //\r
-    // Printf Function Information\r
-    //\r
-    if (FunctionType == 1) {\r
-      sscanf (Line, "%x:%x %xH %s", &SectionNumber, &SectionOffset, &SectionLength, SectionName);\r
-      if (stricmp (SectionName, ".xdata") == 0) {\r
-        FunctionType = 2;\r
-        break;\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
-  if (FunctionType != 2) {\r
-    //\r
-    // no .xdata section is found\r
-    //\r
-    fclose (fpMapFile);\r
-    return;\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
-  // Zero .xdata Section data\r
+  // Set new base address into section header\r
   //\r
-  memset (FileBuffer + SectionHeader[SectionNumber-1].PointerToRawData + SectionOffset, 0, SectionLength);\r
-  DebugMsg (NULL, 0, 9, NULL, "Zero the .xdata section for PE image at Offset 0x%x and Length 0x%x", SectionHeader[SectionNumber-1].PointerToRawData + SectionOffset, SectionLength);\r
-  fclose (fpMapFile);\r
-  return;\r
+  Status = SetAddressToSectionHeader (FileName, FileBuffer, NewPe32BaseAddress);\r
+\r
+  return Status;\r
 }\r
 \r
 int\r
@@ -1362,7 +1059,6 @@ Returns:
   char                             *OutImageName;\r
   char                             *ModuleType;\r
   CHAR8                            *TimeStamp;\r
-  UINT32                           OutImageType;\r
   FILE                             *fpIn;\r
   FILE                             *fpOut;\r
   FILE                             *fpInOut;\r
@@ -1381,11 +1077,14 @@ 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
   BOOLEAN                          ReplaceFlag;\r
   BOOLEAN                          KeepExceptionTableFlag;\r
+  BOOLEAN                          KeepOptionalHeaderFlag;\r
   BOOLEAN                          KeepZeroPendingFlag;\r
   UINT64                           LogLevel;\r
   EFI_TE_IMAGE_HEADER              TEImageHeader;\r
@@ -1397,18 +1096,36 @@ Returns:
   EFI_IMAGE_OPTIONAL_HEADER64      *Optional64;\r
   EFI_IMAGE_DOS_HEADER             BackupDosHdr;\r
   MICROCODE_IMAGE_HEADER           *MciHeader;\r
+  UINT8                            *HiiPackageListBuffer;\r
+  UINT8                            *HiiPackageDataPointer;\r
+  EFI_GUID                         HiiPackageListGuid;\r
+  EFI_HII_PACKAGE_LIST_HEADER      HiiPackageListHeader;\r
+  EFI_HII_PACKAGE_HEADER           HiiPackageHeader;\r
+  EFI_IFR_FORM_SET                 IfrFormSet;\r
+  UINT8                            NumberOfFormPackage;\r
+  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
+  time_t                           InputFileTime;\r
+  time_t                           OutputFileTime;\r
+  struct stat                      Stat_Buf;\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
   OutImageName      = NULL;\r
   ModuleType        = NULL;\r
-  OutImageType      = FW_DUMMY_IMAGE;\r
   Type              = 0;\r
   Status            = STATUS_SUCCESS;\r
   FileBuffer        = NULL;\r
@@ -1425,10 +1142,25 @@ 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
+  KeepOptionalHeaderFlag = FALSE;\r
   KeepZeroPendingFlag    = FALSE;\r
+  NumberOfFormPackage    = 0;\r
+  HiiPackageListBuffer   = NULL;\r
+  HiiPackageDataPointer  = NULL;\r
+  EndPackage.Length      = sizeof (EFI_HII_PACKAGE_HEADER);\r
+  EndPackage.Type        = EFI_HII_PACKAGE_END;\r
+  memset (&HiiPackageListGuid, 0, sizeof (HiiPackageListGuid));\r
+  HiiSectionHeaderSize   = 0;\r
+  HiiSectionHeader       = NULL;\r
+  NewBaseAddress         = 0;\r
+  NegativeAddr           = FALSE;\r
+  InputFileTime          = 0;\r
+  OutputFileTime         = 0;\r
 \r
   if (argc == 1) {\r
     Error (NULL, 0, 1001, "Missing options", "No input options.");\r
@@ -1468,8 +1200,8 @@ Returns:
         goto Finish;\r
       }\r
       ModuleType = argv[1];\r
-      if (OutImageType != FW_TE_IMAGE) {\r
-        OutImageType = FW_EFI_IMAGE;\r
+      if (mOutImageType != FW_TE_IMAGE) {\r
+        mOutImageType = FW_EFI_IMAGE;\r
       }\r
       argc -= 2;\r
       argv += 2;\r
@@ -1477,49 +1209,49 @@ Returns:
     }\r
 \r
     if ((stricmp (argv[0], "-l") == 0) || (stricmp (argv[0], "--stripped") == 0)) {\r
-      OutImageType = FW_RELOC_STRIPEED_IMAGE;\r
+      mOutImageType = FW_RELOC_STRIPEED_IMAGE;\r
       argc --;\r
       argv ++;\r
       continue;\r
     }\r
 \r
     if ((stricmp (argv[0], "-c") == 0) || (stricmp (argv[0], "--acpi") == 0)) {\r
-      OutImageType = FW_ACPI_IMAGE;\r
+      mOutImageType = FW_ACPI_IMAGE;\r
       argc --;\r
       argv ++;\r
       continue;\r
     }\r
 \r
     if ((stricmp (argv[0], "-t") == 0) || (stricmp (argv[0], "--terse") == 0)) {\r
-      OutImageType = FW_TE_IMAGE;\r
+      mOutImageType = FW_TE_IMAGE;\r
       argc --;\r
       argv ++;\r
       continue;\r
     }\r
 \r
     if ((stricmp (argv[0], "-u") == 0) || (stricmp (argv[0], "--dump") == 0)) {\r
-      OutImageType = DUMP_TE_HEADER;\r
+      mOutImageType = DUMP_TE_HEADER;\r
       argc --;\r
       argv ++;\r
       continue;\r
     }\r
 \r
     if ((stricmp (argv[0], "-b") == 0) || (stricmp (argv[0], "--exe2bin") == 0)) {\r
-      OutImageType = FW_BIN_IMAGE;\r
+      mOutImageType = FW_BIN_IMAGE;\r
       argc --;\r
       argv ++;\r
       continue;\r
     }\r
 \r
     if ((stricmp (argv[0], "-z") == 0) || (stricmp (argv[0], "--zero") == 0)) {\r
-      OutImageType = FW_ZERO_DEBUG_IMAGE;\r
+      mOutImageType = FW_ZERO_DEBUG_IMAGE;\r
       argc --;\r
       argv ++;\r
       continue;\r
     }\r
 \r
     if ((stricmp (argv[0], "-s") == 0) || (stricmp (argv[0], "--stamp") == 0)) {\r
-      OutImageType = FW_SET_STAMP_IMAGE;\r
+      mOutImageType = FW_SET_STAMP_IMAGE;\r
       if (argv[1] == NULL || argv[1][0] == '-') {\r
         Error (NULL, 0, 1003, "Invalid option value", "time stamp is missing for -s option");\r
         goto Finish;\r
@@ -1544,6 +1276,13 @@ Returns:
       continue;\r
     }\r
 \r
+    if (stricmp(argv[0], "--keepoptionalheader") == 0) {\r
+      KeepOptionalHeaderFlag = TRUE;\r
+      argc--;\r
+      argv++;\r
+      continue;\r
+    }\r
+\r
     if (stricmp (argv[0], "--keepzeropending") == 0) {\r
       KeepZeroPendingFlag = TRUE;\r
       argc --;\r
@@ -1552,14 +1291,14 @@ Returns:
     }\r
 \r
     if ((stricmp (argv[0], "-m") == 0) || (stricmp (argv[0], "--mcifile") == 0)) {\r
-      OutImageType = FW_MCI_IMAGE;\r
+      mOutImageType = FW_MCI_IMAGE;\r
       argc --;\r
       argv ++;\r
       continue;\r
     }\r
 \r
     if ((stricmp (argv[0], "-j") == 0) || (stricmp (argv[0], "--join") == 0)) {\r
-      OutImageType = FW_MERGE_IMAGE;\r
+      mOutImageType = FW_MERGE_IMAGE;\r
       argc --;\r
       argv ++;\r
       continue;\r
@@ -1576,6 +1315,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
+      mOutImageType = 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
+      mOutImageType = 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
@@ -1610,7 +1387,7 @@ Returns:
         goto Finish;\r
       }\r
       if (LogLevel > 9) {\r
-        Error (NULL, 0, 1003, "Invalid option value", "Debug Level range is 0-9, currnt input level is %d", LogLevel);\r
+        Error (NULL, 0, 1003, "Invalid option value", "Debug Level range is 0-9, currnt input level is %d", (int) LogLevel);\r
         goto Finish;\r
       }\r
       SetPrintLevel (LogLevel);\r
@@ -1619,7 +1396,32 @@ 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
+        Error (NULL, 0, 1003, "Invalid option value", "%s = %s", argv[0], argv[1]);\r
+        goto Finish;\r
+      }\r
+      argc -= 2;\r
+      argv += 2;\r
+      continue;\r
+    }\r
+\r
+    if (stricmp (argv[0], "--hiipackage") == 0) {\r
+      mOutImageType = FW_HII_PACKAGE_LIST_RCIMAGE;\r
+      argc --;\r
+      argv ++;\r
+      continue;\r
+    }\r
+\r
+    if (stricmp (argv[0], "--hiibinpackage") == 0) {\r
+      mOutImageType = FW_HII_PACKAGE_LIST_BINIMAGE;\r
+      argc --;\r
+      argv ++;\r
+      continue;\r
+    }\r
+\r
     if (argv[0][0] == '-') {\r
       Error (NULL, 0, 1000, "Unknown option", argv[0]);\r
       goto Finish;\r
@@ -1631,7 +1433,7 @@ Returns:
       InputFileName = (CHAR8 **) malloc (MAXIMUM_INPUT_FILE_NUM * sizeof (CHAR8 *));\r
       if (InputFileName == NULL) {\r
         Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!");\r
-        return EFI_OUT_OF_RESOURCES;\r
+        goto Finish;\r
       }\r
 \r
       memset (InputFileName, 0, (MAXIMUM_INPUT_FILE_NUM * sizeof (CHAR8 *)));\r
@@ -1640,13 +1442,13 @@ 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
-        return EFI_OUT_OF_RESOURCES;\r
+        goto Finish;\r
       }\r
 \r
       memset (&(InputFileName[InputFileNum]), 0, (MAXIMUM_INPUT_FILE_NUM * sizeof (CHAR8 *)));\r
@@ -1659,7 +1461,7 @@ Returns:
 \r
   VerboseMsg ("%s tool start.", UTILITY_NAME);\r
 \r
-  if (OutImageType == FW_DUMMY_IMAGE) {\r
+  if (mOutImageType == FW_DUMMY_IMAGE) {\r
     Error (NULL, 0, 1001, "Missing option", "No create file action specified; pls specify -e, -c or -t option to create efi image, or acpi table or TeImage!");\r
     if (ReplaceFlag) {\r
       Error (NULL, 0, 1001, "Missing option", "-r option is not supported as the independent option. It can be used together with other create file option specified at the above.");\r
@@ -1678,11 +1480,24 @@ Returns:
   //\r
   // Combine MciBinary files to one file\r
   //\r
-  if ((OutImageType == FW_MERGE_IMAGE) && ReplaceFlag) {\r
+  if ((mOutImageType == FW_MERGE_IMAGE) && ReplaceFlag) {\r
     Error (NULL, 0, 1002, "Conflicting option", "-r replace option cannot be used with -j merge files option.");\r
     goto Finish;\r
   }\r
 \r
+  //\r
+  // Combine HiiBinary packages to a single package list\r
+  //\r
+  if ((mOutImageType == FW_HII_PACKAGE_LIST_RCIMAGE) && ReplaceFlag) {\r
+    Error (NULL, 0, 1002, "Conflicting option", "-r replace option cannot be used with --hiipackage merge files option.");\r
+    goto Finish;\r
+  }\r
+\r
+  if ((mOutImageType == FW_HII_PACKAGE_LIST_BINIMAGE) && ReplaceFlag) {\r
+    Error (NULL, 0, 1002, "Conflicting option", "-r replace option cannot be used with --hiibinpackage merge files option.");\r
+    goto Finish;\r
+  }\r
+\r
   //\r
   // Input image file\r
   //\r
@@ -1692,7 +1507,7 @@ Returns:
   //\r
   // Action will be taken for the input file.\r
   //\r
-  switch (OutImageType) {\r
+  switch (mOutImageType) {\r
   case FW_EFI_IMAGE:\r
     VerboseMsg ("Create efi image on module type %s based on the input PE image.", ModuleType);\r
     break;\r
@@ -1723,6 +1538,18 @@ Returns:
   case FW_MERGE_IMAGE:\r
     VerboseMsg ("Combine the input multi microcode bin files to one bin file.");\r
     break;\r
+  case FW_HII_PACKAGE_LIST_RCIMAGE:\r
+    VerboseMsg ("Combine the input multi hii bin packages to one text pacakge list RC file.");\r
+    break;\r
+  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
@@ -1735,8 +1562,16 @@ Returns:
   // Open output file and Write image into the output file.\r
   //\r
   if (OutImageName != NULL) {\r
-    fpOut = fopen (OutImageName, "rb");\r
+    fpOut = fopen (LongFilePath (OutImageName), "rb");\r
     if (fpOut != NULL) {\r
+      //\r
+      // Get Output file time stamp\r
+      //\r
+      fstat(fileno (fpOut), &Stat_Buf);\r
+      OutputFileTime = Stat_Buf.st_mtime;\r
+      //\r
+      // Get Output file data\r
+      //\r
       OutputFileLength = _filelength (fileno (fpOut));\r
       OutputFileBuffer = malloc (OutputFileLength);\r
       if (OutputFileBuffer == NULL) {\r
@@ -1747,18 +1582,177 @@ Returns:
       }\r
       fread (OutputFileBuffer, 1, OutputFileLength, fpOut);\r
       fclose (fpOut);\r
+      fpOut = NULL;\r
     }\r
-    fpOut = fopen (OutImageName, "wb");\r
+    VerboseMsg ("Output file name is %s", OutImageName);\r
+  } else if (!ReplaceFlag && mOutImageType != 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 (LongFilePath (mInImageName), "rb");\r
+  if (fpIn == NULL) {\r
+    Error (NULL, 0, 0001, "Error opening file", mInImageName);\r
+    goto Finish;\r
+  }\r
+  //\r
+  // Get Iutput file time stamp\r
+  //\r
+  fstat(fileno (fpIn), &Stat_Buf);\r
+  InputFileTime = Stat_Buf.st_mtime;\r
+  //\r
+  // Get Input file data\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 (mOutImageType == FW_HII_PACKAGE_LIST_RCIMAGE || mOutImageType == FW_HII_PACKAGE_LIST_BINIMAGE) {\r
+    //\r
+    // Open output file handle.\r
+    //\r
+    fpOut = fopen (LongFilePath (OutImageName), "wb");\r
     if (!fpOut) {\r
       Error (NULL, 0, 0001, "Error opening output file", OutImageName);\r
       goto Finish;\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
+    //\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 (LongFilePath (InputFileName [Index]), "rb");\r
+      if (fpIn == NULL) {\r
+        Error (NULL, 0, 0001, "Error opening file", InputFileName [Index]);\r
+        goto Finish;\r
+      }\r
+      FileLength = _filelength (fileno (fpIn));\r
+      fread (&HiiPackageHeader, 1, sizeof (HiiPackageHeader), fpIn);\r
+      if (HiiPackageHeader.Type == EFI_HII_PACKAGE_FORM) {\r
+        if (HiiPackageHeader.Length != FileLength) {\r
+          Error (NULL, 0, 3000, "Invalid", "The wrong package size is in HII package file %s", InputFileName [Index]);\r
+          fclose (fpIn);\r
+          goto Finish;\r
+        }\r
+        if (memcmp (&HiiPackageListGuid, &mZeroGuid, sizeof (EFI_GUID)) == 0) {\r
+          fread (&IfrFormSet, 1, sizeof (IfrFormSet), fpIn);\r
+          memcpy (&HiiPackageListGuid, &IfrFormSet.Guid, sizeof (EFI_GUID));\r
+        }\r
+        NumberOfFormPackage ++;\r
+      }\r
+      HiiPackageListHeader.PackageLength += FileLength;\r
+      fclose (fpIn);\r
+    }\r
+    HiiPackageListHeader.PackageLength += sizeof (EndPackage);\r
+    //\r
+    // Check whether hii packages are valid\r
+    //\r
+    if (NumberOfFormPackage > 1) {\r
+      Error (NULL, 0, 3000, "Invalid", "The input hii packages contains more than one hii form package");\r
+      goto Finish;\r
+    }\r
+    if (memcmp (&HiiPackageListGuid, &mZeroGuid, sizeof (EFI_GUID)) == 0) {\r
+      Error (NULL, 0, 3000, "Invalid", "HII pacakge list guid is not specified!");\r
+      goto Finish;\r
+    }\r
+    memcpy (&HiiPackageListHeader.PackageListGuid, &HiiPackageListGuid, sizeof (EFI_GUID));\r
+    //\r
+    // read hii packages\r
+    //\r
+    HiiPackageListBuffer = malloc (HiiPackageListHeader.PackageLength);\r
+    if (HiiPackageListBuffer == NULL) {\r
+      Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!");\r
+      goto Finish;\r
+    }\r
+    memcpy (HiiPackageListBuffer, &HiiPackageListHeader, sizeof (HiiPackageListHeader));\r
+    HiiPackageDataPointer = HiiPackageListBuffer + sizeof (HiiPackageListHeader);\r
+    for (Index = 0; Index < InputFileNum; Index ++) {\r
+      fpIn = fopen (LongFilePath (InputFileName [Index]), "rb");\r
+      if (fpIn == NULL) {\r
+        Error (NULL, 0, 0001, "Error opening file", InputFileName [Index]);\r
+        free (HiiPackageListBuffer);\r
+        goto Finish;\r
+      }\r
+\r
+      FileLength = _filelength (fileno (fpIn));\r
+      fread (HiiPackageDataPointer, 1, FileLength, fpIn);\r
+      fclose (fpIn);\r
+      HiiPackageDataPointer = HiiPackageDataPointer + FileLength;\r
+    }\r
+    memcpy (HiiPackageDataPointer, &EndPackage, sizeof (EndPackage));\r
+\r
+    //\r
+    // write the hii package into the binary package list file with the resource section header\r
+    //\r
+    if (mOutImageType == FW_HII_PACKAGE_LIST_BINIMAGE) {\r
+      //\r
+      // Create the resource section header\r
+      //\r
+      HiiSectionHeader = CreateHiiResouceSectionHeader (&HiiSectionHeaderSize, HiiPackageListHeader.PackageLength);\r
+      if (HiiSectionHeader == NULL) {\r
+        free (HiiPackageListBuffer);\r
+        goto Finish;\r
+      }\r
+      //\r
+      // Wrtie section header and HiiData into File.\r
+      //\r
+      fwrite (HiiSectionHeader, 1, HiiSectionHeaderSize, fpOut);\r
+      fwrite (HiiPackageListBuffer, 1, HiiPackageListHeader.PackageLength, fpOut);\r
+      //\r
+      // Free allocated resources.\r
+      //\r
+      free (HiiSectionHeader);\r
+      free (HiiPackageListBuffer);\r
+      //\r
+      // Done successfully\r
+      //\r
+      goto Finish;\r
+    }\r
+\r
+    //\r
+    // write the hii package into the text package list rc file.\r
+    //\r
+    if (mOutImageType == FW_HII_PACKAGE_LIST_RCIMAGE) {\r
+      for (Index = 0; gHiiPackageRCFileHeader[Index] != NULL; Index++) {\r
+        fprintf (fpOut, "%s\n", gHiiPackageRCFileHeader[Index]);\r
+      }\r
+      fprintf (fpOut, "\n%d %s\n{", HII_RESOURCE_SECTION_INDEX, HII_RESOURCE_SECTION_NAME);\r
+\r
+      HiiPackageDataPointer = HiiPackageListBuffer;\r
+      for (Index = 0; Index + 2 < HiiPackageListHeader.PackageLength; Index += 2) {\r
+        if (Index % 16 == 0) {\r
+          fprintf (fpOut, "\n ");\r
+        }\r
+        fprintf (fpOut, " 0x%04X,", *(UINT16 *) HiiPackageDataPointer);\r
+        HiiPackageDataPointer += 2;\r
+      }\r
+\r
+      if (Index % 16 == 0) {\r
+        fprintf (fpOut, "\n ");\r
+      }\r
+      if ((Index + 2) == HiiPackageListHeader.PackageLength) {\r
+        fprintf (fpOut, " 0x%04X\n}\n", *(UINT16 *) HiiPackageDataPointer);\r
+      }\r
+      if ((Index + 1) == HiiPackageListHeader.PackageLength) {\r
+        fprintf (fpOut, " 0x%04X\n}\n", *(UINT8 *) HiiPackageDataPointer);\r
+      }\r
+      free (HiiPackageListBuffer);\r
+      //\r
+      // Done successfully\r
+      //\r
       goto Finish;\r
     }\r
   }\r
@@ -1766,9 +1760,17 @@ Returns:
   //\r
   // Combine MciBinary files to one file\r
   //\r
-  if (OutImageType == FW_MERGE_IMAGE) {\r
+  if (mOutImageType == FW_MERGE_IMAGE) {\r
+    //\r
+    // Open output file handle.\r
+    //\r
+    fpOut = fopen (LongFilePath (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
+      fpIn = fopen (LongFilePath (InputFileName [Index]), "rb");\r
       if (!fpIn) {\r
         Error (NULL, 0, 0001, "Error opening file", InputFileName [Index]);\r
         goto Finish;\r
@@ -1809,9 +1811,9 @@ Returns:
   //\r
   // Convert MicroCode.txt file to MicroCode.bin file\r
   //\r
-  if (OutImageType == FW_MCI_IMAGE) {\r
-    fpIn = fopen (mInImageName, "r");\r
-    if (!fpIn) {\r
+  if (mOutImageType == FW_MCI_IMAGE) {\r
+    fpIn = fopen (LongFilePath (mInImageName), "r");\r
+    if (fpIn == NULL) {\r
       Error (NULL, 0, 0001, "Error opening file", mInImageName);\r
       goto Finish;\r
     }\r
@@ -1883,7 +1885,7 @@ Returns:
     }\r
 \r
     if (Index != FileLength) {\r
-      Error (NULL, 0, 3000, "Invalid", "file length of %s (0x%x) does not equal expected TotalSize: 0x%04X.", mInImageName, FileLength, Index);\r
+      Error (NULL, 0, 3000, "Invalid", "file length of %s (0x%x) does not equal expected TotalSize: 0x%04X.", mInImageName, (unsigned) FileLength, (unsigned) Index);\r
       goto Finish;\r
     }\r
 \r
@@ -1899,78 +1901,56 @@ Returns:
       Index       += sizeof (*DataPointer);\r
     }\r
     if (CheckSum != 0) {\r
-      Error (NULL, 0, 3000, "Invalid", "checksum (0x%x) failed on file %s.", CheckSum, mInImageName);\r
+      Error (NULL, 0, 3000, "Invalid", "checksum (0x%x) failed on file %s.", (unsigned) CheckSum, mInImageName);\r
       goto Finish;\r
     }\r
     //\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 %d bytes", FileLength);\r
-    //\r
-    //  Convert Mci.TXT to Mci.bin file successfully\r
-    //\r
-    goto Finish;\r
+    VerboseMsg ("the size of output file is %u bytes", (unsigned) FileLength);\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 %d bytes", 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
-  if (OutImageType == DUMP_TE_HEADER) {\r
+  if (mOutImageType == DUMP_TE_HEADER) {\r
     memcpy (&TEImageHeader, FileBuffer, sizeof (TEImageHeader));\r
     if (TEImageHeader.Signature != EFI_TE_IMAGE_HEADER_SIGNATURE) {\r
       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 (LongFilePath (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 (LongFilePath (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
@@ -1978,13 +1958,12 @@ Returns:
       fprintf (fpInOut, "%17X number of sections\n", TEImageHeader.NumberOfSections);\r
       fprintf (fpInOut, "%17X subsystems\n", TEImageHeader.Subsystem);\r
       fprintf (fpInOut, "%17X stripped size\n", TEImageHeader.StrippedSize);\r
-      fprintf (fpInOut, "%17X entry point\n", TEImageHeader.AddressOfEntryPoint);\r
-      fprintf (fpInOut, "%17X base of code\n", TEImageHeader.BaseOfCode);\r
-      fprintf (fpInOut, "%17lX image base\n", (long unsigned int)TEImageHeader.ImageBase);\r
-      fprintf (fpInOut, "%17X [%8X] RVA [size] of Base Relocation Directory\n", TEImageHeader.DataDirectory[0].VirtualAddress, TEImageHeader.DataDirectory[0].Size);\r
-      fprintf (fpInOut, "%17X [%8X] RVA [size] of Debug Directory\n", TEImageHeader.DataDirectory[1].VirtualAddress, TEImageHeader.DataDirectory[1].Size);\r
+      fprintf (fpInOut, "%17X entry point\n", (unsigned) TEImageHeader.AddressOfEntryPoint);\r
+      fprintf (fpInOut, "%17X base of code\n", (unsigned) TEImageHeader.BaseOfCode);\r
+      fprintf (fpInOut, "%17llX image base\n", (unsigned long long)TEImageHeader.ImageBase);\r
+      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
@@ -1992,11 +1971,11 @@ Returns:
       fprintf (fpOut, "%17X number of sections\n", TEImageHeader.NumberOfSections);\r
       fprintf (fpOut, "%17X subsystems\n", TEImageHeader.Subsystem);\r
       fprintf (fpOut, "%17X stripped size\n", TEImageHeader.StrippedSize);\r
-      fprintf (fpOut, "%17X entry point\n", TEImageHeader.AddressOfEntryPoint);\r
-      fprintf (fpOut, "%17X base of code\n", TEImageHeader.BaseOfCode);\r
-      fprintf (fpOut, "%17lX image base\n", (long unsigned int)TEImageHeader.ImageBase);\r
-      fprintf (fpOut, "%17X [%8X] RVA [size] of Base Relocation Directory\n", TEImageHeader.DataDirectory[0].VirtualAddress, TEImageHeader.DataDirectory[0].Size);\r
-      fprintf (fpOut, "%17X [%8X] RVA [size] of Debug Directory\n", TEImageHeader.DataDirectory[1].VirtualAddress, TEImageHeader.DataDirectory[1].Size);\r
+      fprintf (fpOut, "%17X entry point\n", (unsigned) TEImageHeader.AddressOfEntryPoint);\r
+      fprintf (fpOut, "%17X base of code\n", (unsigned) TEImageHeader.BaseOfCode);\r
+      fprintf (fpOut, "%17llX image base\n", (unsigned long long)TEImageHeader.ImageBase);\r
+      fprintf (fpOut, "%17X [%8X] RVA [size] of Base Relocation Directory\n", (unsigned) TEImageHeader.DataDirectory[0].VirtualAddress, (unsigned) TEImageHeader.DataDirectory[0].Size);\r
+      fprintf (fpOut, "%17X [%8X] RVA [size] of Debug Directory\n", (unsigned) TEImageHeader.DataDirectory[1].VirtualAddress, (unsigned) TEImageHeader.DataDirectory[1].Size);\r
     }\r
     goto Finish;\r
   }\r
@@ -2005,12 +1984,12 @@ Returns:
   // Following code to convert dll to efi image or te image.\r
   // Get new image type\r
   //\r
-  if ((OutImageType == FW_EFI_IMAGE) || (OutImageType == FW_TE_IMAGE)) {\r
+  if ((mOutImageType == FW_EFI_IMAGE) || (mOutImageType == FW_TE_IMAGE)) {\r
     if (ModuleType == NULL) {\r
-      if (OutImageType == FW_EFI_IMAGE) {\r
+      if (mOutImageType == FW_EFI_IMAGE) {\r
         Error (NULL, 0, 1001, "Missing option", "EFI_FILETYPE");\r
         goto Finish;\r
-      } else if (OutImageType == FW_TE_IMAGE) {\r
+      } else if (mOutImageType == FW_TE_IMAGE) {\r
         //\r
         // Default TE Image Type is Boot service driver\r
         //\r
@@ -2019,37 +1998,38 @@ 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_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
+        stricmp (ModuleType, "MM_STANDALONE") == 0 ||\r
+        stricmp (ModuleType, "MM_CORE_STANDALONE") == 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
@@ -2059,17 +2039,26 @@ Returns:
   }\r
 \r
   //\r
-  // Convert EFL image to PeImage\r
+  // Convert ELF image to PeImage\r
   //\r
   if (IsElfHeader(FileBuffer)) {\r
-    VerboseMsg ("Convert the input ELF Image to Pe Image");\r
-    ConvertElf(&FileBuffer, &FileLength);\r
+    VerboseMsg ("Convert %s from ELF to PE/COFF.", mInImageName);\r
+    if (!ConvertElf(&FileBuffer, &FileLength)) {\r
+      Error (NULL, 0, 3000, "Invalid", "Unable to convert %s from ELF to PE/COFF.", mInImageName);\r
+      goto Finish;\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
+  //\r
+  PeCoffConvertImageToXip (&FileBuffer, &FileLength);\r
+\r
   //\r
   // Remove reloc section from PE or TE image\r
   //\r
-  if (OutImageType == FW_RELOC_STRIPEED_IMAGE) {\r
+  if (mOutImageType == FW_RELOC_STRIPEED_IMAGE) {\r
     //\r
     // Check TeImage\r
     //\r
@@ -2083,15 +2072,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
@@ -2177,17 +2166,54 @@ 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 (mOutImageType == FW_REBASE_IMAGE || mOutImageType == 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 (mOutImageType == 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
-  if (OutImageType == FW_BIN_IMAGE) {\r
+  if (mOutImageType == FW_BIN_IMAGE) {\r
     if (FileLength < PeHdr->Pe32.OptionalHeader.SizeOfHeaders) {\r
       Error (NULL, 0, 3000, "Invalid", "FileSize of %s is not a legal size.", mInImageName);\r
       goto Finish;\r
@@ -2195,59 +2221,49 @@ 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 %d bytes", FileLength - PeHdr->Pe32.OptionalHeader.SizeOfHeaders);\r
-    goto Finish;\r
+    FileLength = FileLength - PeHdr->Pe32.OptionalHeader.SizeOfHeaders;\r
+    memmove (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
   // Zero Debug Information of Pe Image\r
   //\r
-  if (OutImageType == FW_ZERO_DEBUG_IMAGE) {\r
+  if (mOutImageType == FW_ZERO_DEBUG_IMAGE) {\r
     Status = ZeroDebugData (FileBuffer, TRUE);\r
     if (EFI_ERROR (Status)) {\r
-      Error (NULL, 0, 3000, "Invalid", "Zero DebugData Error status is 0x%lx", (UINTN) Status);\r
+      Error (NULL, 0, 3000, "Invalid", "Zero DebugData Error status is 0x%x", (int) Status);\r
       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
-    VerboseMsg ("the size of output file is %d bytes", FileLength);\r
-    goto Finish;\r
+    //\r
+    // Write the updated Image\r
+    //\r
+    VerboseMsg ("the size of output file is %u bytes", (unsigned) FileLength);\r
+    goto WriteFile;\r
   }\r
 \r
   //\r
   // Set Time Stamp of Pe Image\r
   //\r
-  if (OutImageType == FW_SET_STAMP_IMAGE) {\r
+  if (mOutImageType == FW_SET_STAMP_IMAGE) {\r
     Status = SetStamp (FileBuffer, TimeStamp);\r
     if (EFI_ERROR (Status)) {\r
       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
-    VerboseMsg ("the size of output file is %d bytes", FileLength);\r
-    goto Finish;\r
+    //\r
+    // Write the updated Image\r
+    //\r
+    VerboseMsg ("the size of output file is %u bytes", (unsigned) FileLength);\r
+    goto WriteFile;\r
   }\r
 \r
   //\r
   // Extract acpi data from pe image.\r
   //\r
-  if (OutImageType == FW_ACPI_IMAGE) {\r
+  if (mOutImageType == FW_ACPI_IMAGE) {\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 (strcmp ((char *)SectionHeader->Name, ".data") == 0 || strcmp ((char *)SectionHeader->Name, ".sdata") == 0) {\r
@@ -2268,14 +2284,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
-        VerboseMsg ("the size of output file is %d bytes", FileLength);\r
-        goto Finish;\r
+        memmove (FileBuffer, FileBuffer + SectionHeader->PointerToRawData, FileLength);\r
+        VerboseMsg ("the size of output file is %u bytes", (unsigned) FileLength);\r
+        goto WriteFile;\r
       }\r
     }\r
     Error (NULL, 0, 3000, "Invalid", "failed to get ACPI table from %s.", mInImageName);\r
@@ -2289,9 +2300,9 @@ 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] = DosHdr->e_cp;\r
+      FileBuffer[Index] = (UINT8) DosHdr->e_cp;\r
     }\r
   }\r
 \r
@@ -2304,7 +2315,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
@@ -2312,21 +2323,20 @@ Returns:
 \r
   if (PeHdr->Pe32.OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
     Optional32 = (EFI_IMAGE_OPTIONAL_HEADER32 *)&PeHdr->Pe32.OptionalHeader;\r
-    Optional32->MajorLinkerVersion          = 0;\r
-    Optional32->MinorLinkerVersion          = 0;\r
-    Optional32->MajorOperatingSystemVersion = 0;\r
-    Optional32->MinorOperatingSystemVersion = 0;\r
-    Optional32->MajorImageVersion           = 0;\r
-    Optional32->MinorImageVersion           = 0;\r
-    Optional32->MajorSubsystemVersion       = 0;\r
-    Optional32->MinorSubsystemVersion       = 0;\r
-    Optional32->Win32VersionValue           = 0;\r
-    Optional32->CheckSum                    = 0;\r
-    Optional32->SizeOfStackReserve = 0;\r
-    Optional32->SizeOfStackCommit  = 0;\r
-    Optional32->SizeOfHeapReserve  = 0;\r
-    Optional32->SizeOfHeapCommit   = 0;\r
-\r
+    if (!KeepOptionalHeaderFlag) {\r
+      Optional32->MajorOperatingSystemVersion = 0;\r
+      Optional32->MinorOperatingSystemVersion = 0;\r
+      Optional32->MajorImageVersion = 0;\r
+      Optional32->MinorImageVersion = 0;\r
+      Optional32->MajorSubsystemVersion = 0;\r
+      Optional32->MinorSubsystemVersion = 0;\r
+      Optional32->Win32VersionValue = 0;\r
+      Optional32->CheckSum = 0;\r
+      Optional32->SizeOfStackReserve = 0;\r
+      Optional32->SizeOfStackCommit = 0;\r
+      Optional32->SizeOfHeapReserve = 0;\r
+      Optional32->SizeOfHeapCommit = 0;\r
+    }\r
     TEImageHeader.AddressOfEntryPoint = Optional32->AddressOfEntryPoint;\r
     TEImageHeader.BaseOfCode          = Optional32->BaseOfCode;\r
     TEImageHeader.ImageBase           = (UINT64) (Optional32->ImageBase);\r
@@ -2345,28 +2355,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
@@ -2397,7 +2407,7 @@ Returns:
                 Optional32->SizeOfInitializedData -= (SectionHeader->SizeOfRawData - AllignedRelocSize);\r
                 SectionHeader->SizeOfRawData = AllignedRelocSize;\r
                 FileLength = Optional32->SizeOfImage;\r
-                DebugMsg (NULL, 0, 9, "Remove the zero padding bytes at the end of the base relocations", "The size of padding bytes is %d", SectionHeader->SizeOfRawData - AllignedRelocSize);\r
+                DebugMsg (NULL, 0, 9, "Remove the zero padding bytes at the end of the base relocations", "The size of padding bytes is %u", (unsigned) (SectionHeader->SizeOfRawData - AllignedRelocSize));\r
               }\r
             }\r
           }\r
@@ -2406,21 +2416,20 @@ Returns:
     }\r
   } else if (PeHdr->Pe32.OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC) {\r
     Optional64 = (EFI_IMAGE_OPTIONAL_HEADER64 *)&PeHdr->Pe32.OptionalHeader;\r
-    Optional64->MajorLinkerVersion          = 0;\r
-    Optional64->MinorLinkerVersion          = 0;\r
-    Optional64->MajorOperatingSystemVersion = 0;\r
-    Optional64->MinorOperatingSystemVersion = 0;\r
-    Optional64->MajorImageVersion           = 0;\r
-    Optional64->MinorImageVersion           = 0;\r
-    Optional64->MajorSubsystemVersion       = 0;\r
-    Optional64->MinorSubsystemVersion       = 0;\r
-    Optional64->Win32VersionValue           = 0;\r
-    Optional64->CheckSum                    = 0;\r
-    Optional64->SizeOfStackReserve = 0;\r
-    Optional64->SizeOfStackCommit  = 0;\r
-    Optional64->SizeOfHeapReserve  = 0;\r
-    Optional64->SizeOfHeapCommit   = 0;\r
-\r
+    if (!KeepOptionalHeaderFlag) {\r
+      Optional64->MajorOperatingSystemVersion = 0;\r
+      Optional64->MinorOperatingSystemVersion = 0;\r
+      Optional64->MajorImageVersion = 0;\r
+      Optional64->MinorImageVersion = 0;\r
+      Optional64->MajorSubsystemVersion = 0;\r
+      Optional64->MinorSubsystemVersion = 0;\r
+      Optional64->Win32VersionValue = 0;\r
+      Optional64->CheckSum = 0;\r
+      Optional64->SizeOfStackReserve = 0;\r
+      Optional64->SizeOfStackCommit = 0;\r
+      Optional64->SizeOfHeapReserve = 0;\r
+      Optional64->SizeOfHeapCommit = 0;\r
+    }\r
     TEImageHeader.AddressOfEntryPoint = Optional64->AddressOfEntryPoint;\r
     TEImageHeader.BaseOfCode          = Optional64->BaseOfCode;\r
     TEImageHeader.ImageBase           = (UINT64) (Optional64->ImageBase);\r
@@ -2441,39 +2450,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
                 }\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
@@ -2505,7 +2515,7 @@ Returns:
                 Optional64->SizeOfInitializedData -= (SectionHeader->SizeOfRawData - AllignedRelocSize);\r
                 SectionHeader->SizeOfRawData = AllignedRelocSize;\r
                 FileLength = Optional64->SizeOfImage;\r
-                DebugMsg (NULL, 0, 9, "Remove the zero padding bytes at the end of the base relocations", "The size of padding bytes is %d", SectionHeader->SizeOfRawData - AllignedRelocSize);\r
+                DebugMsg (NULL, 0, 9, "Remove the zero padding bytes at the end of the base relocations", "The size of padding bytes is %u", (unsigned) (SectionHeader->SizeOfRawData - AllignedRelocSize));\r
               }\r
             }\r
           }\r
@@ -2516,27 +2526,66 @@ 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
+      // 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
+  // Fill HII section data\r
+  //\r
+  SectionHeader = (EFI_IMAGE_SECTION_HEADER *) ((UINT8 *) &(PeHdr->Pe32.OptionalHeader) + PeHdr->Pe32.FileHeader.SizeOfOptionalHeader);\r
+  for (Index = 0; Index < PeHdr->Pe32.FileHeader.NumberOfSections; Index++) {\r
+    if (stricmp ((char *)SectionHeader[Index].Name, ".hii") == 0) {\r
+      //\r
+      // Update resource section header offset\r
+      //\r
+      SetHiiResourceHeader ((UINT8*) FileBuffer + SectionHeader[Index].PointerToRawData, SectionHeader[Index].VirtualAddress);\r
+      //\r
+      // Update resource section name\r
+      //\r
+      strcpy((char *) SectionHeader[Index].Name, ".rsrc");\r
+      //\r
+      // Update resource data directory.\r
+      //\r
+      if (PeHdr->Pe32.OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
+        Optional32 = (EFI_IMAGE_OPTIONAL_HEADER32 *)&PeHdr->Pe32.OptionalHeader;\r
+        Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress = SectionHeader[Index].VirtualAddress;\r
+        Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE].Size = SectionHeader[Index].Misc.VirtualSize;\r
+      } else if (PeHdr->Pe32.OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC) {\r
+        Optional64 = (EFI_IMAGE_OPTIONAL_HEADER64 *)&PeHdr->Pe32.OptionalHeader;\r
+        Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress = SectionHeader[Index].VirtualAddress;\r
+        Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE].Size = SectionHeader[Index].Misc.VirtualSize;\r
+      }\r
+      break;\r
     }\r
   }\r
-   \r
+\r
   //\r
   // Zero ExceptionTable Xdata\r
   //\r
   if (!KeepExceptionTableFlag) {\r
     SectionHeader = (EFI_IMAGE_SECTION_HEADER *) ((UINT8 *) &(PeHdr->Pe32.OptionalHeader) + PeHdr->Pe32.FileHeader.SizeOfOptionalHeader);\r
-    ZeroXdataSection(mInImageName, FileBuffer, SectionHeader, PeHdr->Pe32.FileHeader.NumberOfSections);\r
+    for (Index = 0; Index < PeHdr->Pe32.FileHeader.NumberOfSections; Index++) {\r
+      if (stricmp ((char *)SectionHeader[Index].Name, ".xdata") == 0) {\r
+        //\r
+        // zero .xdata section\r
+        //\r
+        memset (FileBuffer + SectionHeader[Index].PointerToRawData, 0, SectionHeader[Index].SizeOfRawData);\r
+        DebugMsg (NULL, 0, 9, NULL, "Zero the .xdata section for PE image at Offset 0x%x and Length 0x%x", (unsigned) SectionHeader[Index].PointerToRawData, (unsigned) SectionHeader[Index].SizeOfRawData);\r
+        break;\r
+      }\r
+    }\r
   }\r
 \r
   //\r
@@ -2544,7 +2593,7 @@ Returns:
   //\r
   ZeroDebugData (FileBuffer, FALSE);\r
 \r
-  if (OutImageType == FW_TE_IMAGE) {\r
+  if (mOutImageType == FW_TE_IMAGE) {\r
     if ((PeHdr->Pe32.FileHeader.NumberOfSections &~0xFF) || (Type &~0xFF)) {\r
       //\r
       // Pack the subsystem and NumberOfSections into 1 byte. Make sure they fit both.\r
@@ -2561,41 +2610,79 @@ Returns:
       goto Finish;\r
     }\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 %X",\r
-              TEImageHeader.Machine, TEImageHeader.NumberOfSections, TEImageHeader.StrippedSize, TEImageHeader.AddressOfEntryPoint, TEImageHeader.BaseOfCode, TEImageHeader.ImageBase);\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
     //\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
+    FileLength = FileLength - TEImageHeader.StrippedSize;\r
+    memmove (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
+  } else {\r
+\r
+    //\r
+    // Following codes are to fix the objcopy's issue:\r
+    // objcopy in binutil 2.50.18 will set PE image's charactices to "RELOC_STRIPPED" if image has no ".reloc" section\r
+    // It cause issue for EFI image which has no ".reloc" sections.\r
+    // Following codes will be removed when objcopy in binutil fix this problem for PE image.\r
+    //\r
+    if ((PeHdr->Pe32.FileHeader.Characteristics & EFI_IMAGE_FILE_RELOCS_STRIPPED) != 0) {\r
+      if (PeHdr->Pe32.OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
+        Optional32 = (EFI_IMAGE_OPTIONAL_HEADER32 *)&PeHdr->Pe32.OptionalHeader;\r
+        if (Optional32->ImageBase == 0) {\r
+          PeHdr->Pe32.FileHeader.Characteristics &= ~EFI_IMAGE_FILE_RELOCS_STRIPPED;\r
+        }\r
+      } else if (PeHdr->Pe32.OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC) {\r
+        Optional64 = (EFI_IMAGE_OPTIONAL_HEADER64 *)&PeHdr->Pe32.OptionalHeader;\r
+        if (Optional64->ImageBase == 0) {\r
+          PeHdr->Pe32.FileHeader.Characteristics &= ~EFI_IMAGE_FILE_RELOCS_STRIPPED;\r
+        }\r
+      }\r
     }\r
-    VerboseMsg ("the size of output file is %d bytes", FileLength - TEImageHeader.StrippedSize);\r
-    goto Finish;\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 (LongFilePath (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 ((OutputFileTime < InputFileTime) || (FileLength != OutputFileLength) || (memcmp (FileBuffer, OutputFileBuffer, FileLength) != 0)) {\r
+      //\r
+      // Update File when File is changed or File is old.\r
+      //\r
+      fpOut = fopen (LongFilePath (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 %d bytes", 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
@@ -2620,14 +2707,41 @@ Finish:
       if (OutputFileBuffer == NULL) {\r
         remove (OutImageName);\r
       } else {\r
-        fpOut = fopen (OutImageName, "wb");\r
+        fpOut = fopen (LongFilePath (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 (LongFilePath (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
@@ -2659,6 +2773,7 @@ Returns:
 {\r
   UINT32                           Index;\r
   UINT32                           DebugDirectoryEntryRva;\r
+  UINT32                           DebugDirectoryEntrySize;\r
   UINT32                           DebugDirectoryEntryFileOffset;\r
   UINT32                           ExportDirectoryEntryRva;\r
   UINT32                           ExportDirectoryEntryFileOffset;\r
@@ -2670,12 +2785,14 @@ Returns:
   EFI_IMAGE_OPTIONAL_HEADER64     *Optional64Hdr;\r
   EFI_IMAGE_SECTION_HEADER        *SectionHeader;\r
   EFI_IMAGE_DEBUG_DIRECTORY_ENTRY *DebugEntry;\r
+  EFI_IMAGE_DEBUG_CODEVIEW_RSDS_ENTRY *RsdsEntry;\r
   UINT32                          *NewTimeStamp;  \r
 \r
   //\r
   // Init variable.\r
   //\r
   DebugDirectoryEntryRva           = 0;\r
+  DebugDirectoryEntrySize          = 0;\r
   ExportDirectoryEntryRva          = 0;\r
   ResourceDirectoryEntryRva        = 0;\r
   DebugDirectoryEntryFileOffset    = 0;\r
@@ -2697,8 +2814,9 @@ Returns:
   // Get Debug, Export and Resource EntryTable RVA address.\r
   // Resource Directory entry need to review.\r
   //\r
-  if (FileHdr->Machine == EFI_IMAGE_MACHINE_IA32) {\r
-    Optional32Hdr = (EFI_IMAGE_OPTIONAL_HEADER32 *) ((UINT8*) FileHdr + sizeof (EFI_IMAGE_FILE_HEADER));\r
+  Optional32Hdr = (EFI_IMAGE_OPTIONAL_HEADER32 *) ((UINT8*) FileHdr + sizeof (EFI_IMAGE_FILE_HEADER));\r
+  Optional64Hdr = (EFI_IMAGE_OPTIONAL_HEADER64 *) ((UINT8*) FileHdr + sizeof (EFI_IMAGE_FILE_HEADER));\r
+  if (Optional32Hdr->Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
     SectionHeader = (EFI_IMAGE_SECTION_HEADER *) ((UINT8 *) Optional32Hdr +  FileHdr->SizeOfOptionalHeader);\r
     if (Optional32Hdr->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_EXPORT && \\r
         Optional32Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXPORT].Size != 0) {\r
@@ -2711,13 +2829,13 @@ Returns:
     if (Optional32Hdr->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_DEBUG && \\r
         Optional32Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].Size != 0) {\r
       DebugDirectoryEntryRva = Optional32Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress;\r
+      DebugDirectoryEntrySize = Optional32Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].Size;\r
       if (ZeroDebugFlag) {\r
         Optional32Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].Size = 0;\r
         Optional32Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress = 0;\r
       }\r
     }\r
   } else {\r
-    Optional64Hdr = (EFI_IMAGE_OPTIONAL_HEADER64 *) ((UINT8*) FileHdr + sizeof (EFI_IMAGE_FILE_HEADER));\r
     SectionHeader = (EFI_IMAGE_SECTION_HEADER *) ((UINT8 *) Optional64Hdr +  FileHdr->SizeOfOptionalHeader);\r
     if (Optional64Hdr->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_EXPORT && \\r
         Optional64Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXPORT].Size != 0) {\r
@@ -2730,6 +2848,7 @@ Returns:
     if (Optional64Hdr->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_DEBUG && \\r
         Optional64Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].Size != 0) {\r
       DebugDirectoryEntryRva = Optional64Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress;\r
+      DebugDirectoryEntrySize = Optional64Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].Size;\r
       if (ZeroDebugFlag) {\r
         Optional64Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].Size = 0;\r
         Optional64Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress = 0;\r
@@ -2762,7 +2881,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
@@ -2775,10 +2894,33 @@ Returns:
 \r
   if (DebugDirectoryEntryFileOffset != 0) {\r
     DebugEntry = (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY *) (FileBuffer + DebugDirectoryEntryFileOffset);\r
-    DebugEntry->TimeDateStamp = 0;\r
-    if (ZeroDebugFlag) {\r
-      memset (FileBuffer + DebugEntry->FileOffset, 0, DebugEntry->SizeOfData);\r
-      memset (DebugEntry, 0, sizeof (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY));\r
+    Index = 0;\r
+    for (Index=0; Index < DebugDirectoryEntrySize / sizeof (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY); Index ++, DebugEntry ++) {\r
+      DebugEntry->TimeDateStamp = 0;\r
+      if (ZeroDebugFlag || DebugEntry->Type != EFI_IMAGE_DEBUG_TYPE_CODEVIEW) {\r
+        memset (FileBuffer + DebugEntry->FileOffset, 0, DebugEntry->SizeOfData);\r
+        memset (DebugEntry, 0, sizeof (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY));\r
+      }\r
+      if (DebugEntry->Type == EFI_IMAGE_DEBUG_TYPE_CODEVIEW) {\r
+        RsdsEntry = (EFI_IMAGE_DEBUG_CODEVIEW_RSDS_ENTRY *) (FileBuffer + DebugEntry->FileOffset);\r
+        if (RsdsEntry->Signature == CODEVIEW_SIGNATURE_RSDS) {\r
+          RsdsEntry->Unknown  = 0;\r
+          RsdsEntry->Unknown2 = 0;\r
+          RsdsEntry->Unknown3 = 0;\r
+          RsdsEntry->Unknown4 = 0;\r
+          RsdsEntry->Unknown5 = 0;\r
+        } else if (RsdsEntry->Signature == CODEVIEW_SIGNATURE_MTOC) {\r
+          // MTOC sets DebugDirectoryEntrySize to size of the .debug section, so fix it.\r
+          if (!ZeroDebugFlag) {\r
+            if (Optional32Hdr->Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
+              Optional32Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].Size = sizeof (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY);\r
+            } else {\r
+              Optional64Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].Size = sizeof (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY);\r
+            }\r
+          }\r
+          break;\r
+        }\r
+      }\r
     }\r
   }\r
 \r
@@ -2813,13 +2955,13 @@ Returns:
   struct tm                       stime;\r
   struct tm                       *ptime;\r
   time_t                          newtime;\r
-  UINT32                           Index;\r
-  UINT32                           DebugDirectoryEntryRva;\r
-  UINT32                           DebugDirectoryEntryFileOffset;\r
-  UINT32                           ExportDirectoryEntryRva;\r
-  UINT32                           ExportDirectoryEntryFileOffset;\r
-  UINT32                           ResourceDirectoryEntryRva;\r
-  UINT32                           ResourceDirectoryEntryFileOffset;\r
+  UINT32                          Index;\r
+  UINT32                          DebugDirectoryEntryRva;\r
+  UINT32                          DebugDirectoryEntryFileOffset;\r
+  UINT32                          ExportDirectoryEntryRva;\r
+  UINT32                          ExportDirectoryEntryFileOffset;\r
+  UINT32                          ResourceDirectoryEntryRva;\r
+  UINT32                          ResourceDirectoryEntryFileOffset;\r
   EFI_IMAGE_DOS_HEADER            *DosHdr;\r
   EFI_IMAGE_FILE_HEADER           *FileHdr;\r
   EFI_IMAGE_OPTIONAL_HEADER32     *Optional32Hdr;\r
@@ -2830,9 +2972,12 @@ Returns:
   //\r
   // Init variable.\r
   //\r
-  DebugDirectoryEntryRva    = 0;\r
-  ExportDirectoryEntryRva   = 0;\r
-  ResourceDirectoryEntryRva = 0;\r
+  DebugDirectoryEntryRva           = 0;\r
+  DebugDirectoryEntryFileOffset    = 0;\r
+  ExportDirectoryEntryRva          = 0;\r
+  ExportDirectoryEntryFileOffset   = 0;\r
+  ResourceDirectoryEntryRva        = 0;\r
+  ResourceDirectoryEntryFileOffset = 0;\r
   //\r
   // Get time and date that will be set.\r
   //\r
@@ -2925,8 +3070,10 @@ Returns:
   }\r
 \r
   ptime = localtime (&newtime);\r
-  DebugMsg (NULL, 0, 9, "New Image Time Stamp", "%04d-%02d-%02d %02d:%02d:%02d",\r
-            ptime->tm_year + 1900, ptime->tm_mon + 1, ptime->tm_mday, ptime->tm_hour, ptime->tm_min, ptime->tm_sec);\r
+  if (ptime != NULL) {\r
+    DebugMsg (NULL, 0, 9, "New Image Time Stamp", "%04d-%02d-%02d %02d:%02d:%02d",\r
+              ptime->tm_year + 1900, ptime->tm_mon + 1, ptime->tm_mday, ptime->tm_hour, ptime->tm_min, ptime->tm_sec);\r
+  }\r
   //\r
   // Set new time and data into PeImage.\r
   //\r
@@ -2999,7 +3146,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
@@ -3041,6 +3188,7 @@ Returns:
 {\r
   CHAR8  Line[MAX_LINE_LEN];\r
   CHAR8  *cptr;\r
+  int    ScannedData = 0;\r
 \r
   Line[MAX_LINE_LEN - 1]  = 0;\r
   while (1) {\r
@@ -3057,7 +3205,7 @@ Returns:
     //\r
     // strip space\r
     //\r
-    for (cptr = Line; *cptr && isspace(*cptr); cptr++) {\r
+    for (cptr = Line; *cptr && isspace((int)*cptr); cptr++) {\r
     }\r
 \r
     // Skip Blank Lines and Comment Lines\r
@@ -3072,18 +3220,19 @@ Returns:
   // DD  XXXXXXXXX\r
   //  DD XXXXXXXXX\r
   //\r
-  if ((tolower(cptr[0]) == 'd') && (tolower(cptr[1]) == 'd') && isspace (cptr[2])) {\r
+  if ((tolower((int)cptr[0]) == 'd') && (tolower((int)cptr[1]) == 'd') && isspace ((int)cptr[2])) {\r
     //\r
     // Skip blanks and look for a hex digit\r
     //\r
     cptr += 3;\r
-    for (; *cptr && isspace(*cptr); cptr++) {\r
+    for (; *cptr && isspace((int)*cptr); cptr++) {\r
     }\r
-    if (isxdigit (*cptr)) {\r
-      if (sscanf (cptr, "%X", Data) != 1) {\r
+    if (isxdigit ((int)*cptr)) {\r
+      if (sscanf (cptr, "%X", &ScannedData) != 1) {\r
         return STATUS_ERROR;\r
       }\r
     }\r
+    *Data = (UINT32) ScannedData;\r
     return STATUS_SUCCESS;\r
   }\r
 \r