Add GenFfs tool, PeCoffLoader library and update GenFv tool to support Rebase function.
authorlgao4 <lgao4@7335b38e-4728-0410-8992-fb3ffe349368>
Fri, 22 Jun 2007 09:50:38 +0000 (09:50 +0000)
committerlgao4 <lgao4@7335b38e-4728-0410-8992-fb3ffe349368>
Fri, 22 Jun 2007 09:50:38 +0000 (09:50 +0000)
git-svn-id: https://buildtools.tianocore.org/svn/buildtools/trunk/BaseTools@181 7335b38e-4728-0410-8992-fb3ffe349368

13 files changed:
Source/C/Common/FvLib.h
Source/C/GenFfs/GNUmakefile [new file with mode: 0644]
Source/C/GenFfs/GenFfs.c [new file with mode: 0644]
Source/C/GenFfs/Makefile [new file with mode: 0644]
Source/C/GenFv/GenFv.c
Source/C/GenFv/GenFvInternalLib.c
Source/C/GenFv/GenFvInternalLib.h
Source/C/GenFv/Makefile
Source/C/GenSec/GenSec.c
Source/C/Makefile
Source/C/PeCoffLoader/BasePeCoff.c [new file with mode: 0644]
Source/C/PeCoffLoader/Makefile [new file with mode: 0644]
Source/C/PeCoffLoader/PeCoffLoaderEx.c [new file with mode: 0644]

index 3096f70..f0dbffa 100644 (file)
@@ -28,7 +28,6 @@ Abstract:
 #include <string.h>\r
 \r
 #include <Common/UefiBaseTypes.h>\r
-#include <Common/EfiImage.h>\r
 #include <Common/FirmwareVolumeImageFormat.h>\r
 #include <Common/PiFirmwareFileSystem.h>\r
 #include <Common/PiFirmwareVolumeHeader.h>\r
diff --git a/Source/C/GenFfs/GNUmakefile b/Source/C/GenFfs/GNUmakefile
new file mode 100644 (file)
index 0000000..239c473
--- /dev/null
@@ -0,0 +1,11 @@
+ARCH ?= IA32
+MAKEROOT ?= ..
+
+APPNAME = GenFfs
+
+OBJECTS = GenFfs.o
+
+include $(MAKEROOT)/app.makefile
+
+LIBS = -lCommon
+
diff --git a/Source/C/GenFfs/GenFfs.c b/Source/C/GenFfs/GenFfs.c
new file mode 100644 (file)
index 0000000..4f30ca1
--- /dev/null
@@ -0,0 +1,672 @@
+/*++\r
+\r
+Copyright (c) 2004-2007, Intel Corporation                                                         \r
+All rights reserved. This program and the accompanying materials                          \r
+are licensed and made available under the terms and conditions of the BSD License         \r
+which accompanies this distribution.  The full text of the license may be found at        \r
+http://opensource.org/licenses/bsd-license.php                                            \r
+                                                                                          \r
+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
+  GenFfs.c\r
+\r
+Abstract:\r
+\r
+  This file contains functions required to generate a Firmware File System\r
+  file.\r
+\r
+--*/\r
+\r
+#include <stdio.h>\r
+#include <stdlib.h>\r
+#include <string.h>\r
+\r
+#include <Common/UefiBaseTypes.h>\r
+#include <Common/FirmwareVolumeImageFormat.h>\r
+#include <Common/PiFirmwareFileSystem.h>\r
+\r
+#include "CommonLib.h"\r
+#include "EfiUtilityMsgs.h"\r
+\r
+#define UTILITY_NAME            "GenFfs"\r
+#define UTILITY_MAJOR_VERSION   1\r
+#define UTILITY_MINOR_VERSION   0\r
+\r
+#define MAXIMUM_INPUT_FILE_NUM 10\r
+\r
+static CHAR8 *mFfsFileType[] = {\r
+  NULL,                                   // 0x00\r
+  "EFI_FV_FILETYPE_RAW",                  // 0x01\r
+  "EFI_FV_FILETYPE_FREEFORM",             // 0x02\r
+  "EFI_FV_FILETYPE_SECURITY_CORE",        // 0x03\r
+  "EFI_FV_FILETYPE_PEI_CORE",             // 0x04\r
+  "EFI_FV_FILETYPE_DXE_CORE",             // 0x05\r
+  "EFI_FV_FILETYPE_PEIM",                 // 0x06\r
+  "EFI_FV_FILETYPE_DRIVER",               // 0x07\r
+  "EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER", // 0x08\r
+  "EFI_FV_FILETYPE_APPLICATION",          // 0x09\r
+  NULL,                                   // 0x0A - reserved\r
+  "EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE" // 0x0B\r
+ };\r
+\r
+static CHAR8 *mAlignName[] = {\r
+  "1", "2", "4", "8", "16", "32", "64", "128", "256", "512",\r
+  "1K", "2K", "4K", "8K", "16K", "32K", "64K"\r
+ };\r
+\r
+static CHAR8 *mFfsValidAlignName[] = {\r
+  "8", "16", "128", "512", "1K", "4K", "32K", "64K"\r
+ };\r
+\r
+static UINT32 mFfsValidAlign[] = {0, 8, 16, 128, 512, 1024, 4096, 32768, 65536};\r
+\r
+static EFI_GUID mZeroGuid = {0};\r
+\r
+static\r
+void \r
+Version(\r
+  void\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Print out version information for this utility.\r
+\r
+Arguments:\r
+\r
+  None\r
+  \r
+Returns:\r
+\r
+  None\r
+  \r
+--*/ \r
+{\r
+  printf ("%s v%d.%d - EDKII utility to generate a Firmware File System files.\n", UTILITY_NAME, UTILITY_MAJOR_VERSION, UTILITY_MINOR_VERSION);\r
+  printf ("Copyright (c) 2007 Intel Corporation. All rights reserved.\n");\r
+}\r
+\r
+static\r
+void\r
+Usage (\r
+  void\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Print Error / Help message.\r
+\r
+Arguments:\r
+\r
+  void\r
+\r
+Returns:\r
+\r
+  None\r
+\r
+--*/\r
+{\r
+  Version();\r
+  \r
+  printf ("\nUsage: " UTILITY_NAME "\n\\r
+        -o, --outputfile [FileName]\n\\r
+        -t, --filetype <EFI_FV_FILETYPE_RAW|\n\\r
+                        EFI_FV_FILETYPE_FREEFORM|\n\\r
+                        EFI_FV_FILETYPE_SECURITY_CORE|\n\\r
+                        EFI_FV_FILETYPE_PEI_CORE|\n\\r
+                        EFI_FV_FILETYPE_DXE_CORE|\n\\r
+                        EFI_FV_FILETYPE_PEIM|\n\\r
+                        EFI_FV_FILETYPE_DRIVER|\n\\r
+                        EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER|\n\\r
+                        EFI_FV_FILETYPE_APPLICATION|\n\\r
+                        EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE>|\n\\r
+        -g, --fileguid [GuidValue (########-####-####-####-############)]\n\\r
+        -x, --fixed\n\\r
+        -s, --checksum\n\\r
+        -a, --align <8,16,128,512,1K,4K,32K,64K>\n\\r
+        -i, --sectionfile [FileName] [-n, --sectionalign <1~64K>]\n\\r
+        -h, --help\n\\r
+        -V, --version\n");\r
+}\r
+\r
+static\r
+EFI_STATUS\r
+StringtoAlignment (\r
+  IN  CHAR8  *AlignBuffer,\r
+  OUT UINT32 *AlignNumber\r
+  )\r
+{\r
+  UINT32 Index = 0;\r
+  for (Index = 0; Index < sizeof (mAlignName) / sizeof (CHAR8 *); Index ++) {\r
+    if (stricmp (AlignBuffer, mAlignName [Index]) == 0) {\r
+      *AlignNumber = Index;\r
+      return EFI_SUCCESS;\r
+    }\r
+  }\r
+  return EFI_INVALID_PARAMETER;\r
+}\r
+\r
+static\r
+UINT8\r
+StringToType (\r
+  IN CHAR8 *String\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Converts File Type String to value.  EFI_FV_FILETYPE_ALL indicates that an\r
+  unrecognized file type was specified.\r
+\r
+Arguments:\r
+\r
+  String    - File type string\r
+\r
+Returns:\r
+\r
+  File Type Value\r
+\r
+--*/\r
+{\r
+  UINT8 Index = 0;\r
+  \r
+  if (String == NULL) {\r
+    return EFI_FV_FILETYPE_ALL;\r
+  }\r
+\r
+  for (Index = 0; Index < sizeof (mFfsFileType) / sizeof (CHAR8 *); Index ++) {\r
+    if (mFfsFileType [Index] != NULL && (stricmp (String, mFfsFileType [Index]) == 0)) {\r
+      return Index;\r
+    }\r
+  }\r
+  return EFI_FV_FILETYPE_ALL;\r
+}\r
+\r
+static\r
+EFI_STATUS\r
+GetSectionContents (\r
+  IN  CHAR8   **InputFileName,\r
+  IN  UINT32  *InputFileAlign,\r
+  IN  UINT32  InputFileNum,\r
+  OUT UINT8   *FileBuffer,\r
+  OUT UINT32  *BufferLength,\r
+  OUT UINT32  *MaxAlignment\r
+  )\r
+/*++\r
+        \r
+Routine Description:\r
+           \r
+  Get the contents of all section files specified in InputFileName\r
+  into FileBuffer.\r
+            \r
+Arguments:\r
+               \r
+  InputFileName  - Name of the input file.\r
+                \r
+  InputFileAlign - Alignment required by the input file data.\r
+\r
+  InputFileNum   - Number of input files. Should be at least 1.\r
+\r
+  FileBuffer     - Output buffer to contain data\r
+\r
+  BufferLength   - On input, this is size of the FileBuffer. \r
+                   On output, this is the actual length of the data.\r
+\r
+  MaxAlignment   - The max alignment required by all the input file datas.\r
+\r
+Returns:\r
+                       \r
+  EFI_SUCCESS on successful return\r
+  EFI_INVALID_PARAMETER if InputFileNum is less than 1 or BufferLength point is NULL.\r
+  EFI_ABORTED if unable to open input file.\r
+  EFI_BUFFER_TOO_SMALL FileBuffer is not enough to contain all file data.\r
+--*/\r
+{\r
+  UINT32                     Size;\r
+  UINT32                     Offset;\r
+  UINT32                     FileSize;\r
+  UINT32                     Index;\r
+  FILE                       *InFile;\r
+  EFI_COMMON_SECTION_HEADER  *SectHeader;\r
+\r
+  Size          = 0;\r
+  Offset        = 0;\r
+  *MaxAlignment = 0;\r
+  //\r
+  // Go through our array of file names and copy their contents\r
+  // to the output buffer.\r
+  //\r
+  for (Index = 0; Index < InputFileNum; Index++) {\r
+    //\r
+    // make sure section ends on a DWORD boundary\r
+    //\r
+    while ((Size & 0x03) != 0) {\r
+      Size++;\r
+    }\r
+    \r
+    //\r
+    // Get the Max alignment of all input file datas\r
+    //\r
+    if (*MaxAlignment < (1 << InputFileAlign [Index])) {\r
+      *MaxAlignment = 1 << InputFileAlign [Index];\r
+    }\r
+    \r
+    //\r
+    // make sure section data meet its alignment requirement.\r
+    // But the different sections have the different section header. Necessary or not?\r
+    // Based on section type to adjust offset? Todo\r
+    //\r
+    if (((Size + sizeof (EFI_COMMON_SECTION_HEADER)) % (1 << InputFileAlign [Index])) != 0) {\r
+      Offset = ((Size + 2 * sizeof (EFI_COMMON_SECTION_HEADER) + (1 << InputFileAlign [Index]) - 1) & ~((1 << InputFileAlign [Index]) - 1)) - Size;\r
+      Offset = Offset - sizeof (EFI_COMMON_SECTION_HEADER);\r
+       \r
+      if (FileBuffer != NULL && ((Size + Offset) < *BufferLength)) {\r
+        SectHeader          = (EFI_COMMON_SECTION_HEADER *) FileBuffer;\r
+        SectHeader->Type    = EFI_SECTION_RAW;\r
+        SectHeader->Size[0] = (UINT8) (Offset & 0xff);\r
+        SectHeader->Size[1] = (UINT8) ((Offset & 0xff00) >> 8);\r
+        SectHeader->Size[2] = (UINT8) ((Offset & 0xff0000) >> 16);\r
+      }\r
+\r
+      Size = Size + Offset;\r
+    }\r
+    \r
+    // \r
+    // Open file and read contents\r
+    //\r
+    InFile = fopen (InputFileName[Index], "rb");\r
+    if (InFile == NULL) {\r
+      Error (NULL, 0, 0, InputFileName[Index], "failed to open input file");\r
+      return EFI_ABORTED;\r
+    }\r
+\r
+    fseek (InFile, 0, SEEK_END);\r
+    FileSize = ftell (InFile);\r
+    fseek (InFile, 0, SEEK_SET);\r
+    //\r
+    // Now read the contents of the file into the buffer\r
+    // Buffer must be enough to contain the file content.\r
+    //\r
+    if (FileSize > 0 && FileBuffer != NULL && (Size + FileSize) <= *BufferLength) {\r
+      if (fread (FileBuffer + Size, (size_t) FileSize, 1, InFile) != 1) {\r
+        Error (NULL, 0, 0, InputFileName[Index], "failed to read contents of input file");\r
+        fclose (InFile);\r
+        return EFI_ABORTED;\r
+      }\r
+    }\r
+\r
+    fclose (InFile);\r
+    Size += FileSize;\r
+  }\r
+  \r
+  if (Size > *BufferLength) {\r
+    *BufferLength = Size;\r
+    return EFI_BUFFER_TOO_SMALL;\r
+  } else {\r
+    *BufferLength = Size;\r
+    return EFI_SUCCESS;\r
+  }\r
+}\r
+\r
+int\r
+main (\r
+  INT32 argc,\r
+  CHAR8 *argv[]\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Main function.\r
+\r
+Arguments:\r
+\r
+  argc - Number of command line parameters.\r
+  argv - Array of pointers to parameter strings.\r
+\r
+Returns:\r
+  STATUS_SUCCESS - Utility exits successfully.\r
+  STATUS_ERROR   - Some error occurred during execution.\r
+\r
+--*/\r
+{\r
+  EFI_STATUS              Status;\r
+  EFI_FFS_FILE_ATTRIBUTES FfsAttrib;\r
+  UINT32                  FfsAlign;\r
+  EFI_FV_FILETYPE         FfsFiletype;\r
+  CHAR8                   *OutputFileName;\r
+  EFI_GUID                FileGuid = {0};\r
+  UINT32                  InputFileNum;\r
+  UINT32                  *InputFileAlign;\r
+  CHAR8                   **InputFileName;\r
+  UINT8                   *FileBuffer;\r
+  UINT32                  FileSize;\r
+  UINT32                  MaxAlignment;\r
+  EFI_FFS_FILE_HEADER     FfsFileHeader;\r
+  FILE                    *FfsFile;\r
+  UINT32                  Index;\r
+\r
+  Index          = 0;\r
+  FfsAttrib      = 0;  \r
+  FfsAlign       = 0;\r
+  FfsFiletype    = 0;\r
+  OutputFileName = NULL;\r
+  InputFileNum   = 0;\r
+  InputFileName  = NULL;\r
+  InputFileAlign = NULL;\r
+  FileBuffer     = NULL;\r
+  FileSize       = 0;\r
+  MaxAlignment   = 1;\r
+  FfsFile        = NULL;\r
+  Status         = EFI_SUCCESS;\r
+  \r
+  SetUtilityName (UTILITY_NAME);\r
+\r
+  if (argc == 1) {\r
+    Usage ();\r
+    return STATUS_ERROR;\r
+  }\r
+\r
+  //\r
+  // Parse command line\r
+  //\r
+  argc --;\r
+  argv ++;\r
+\r
+  if ((stricmp (argv[0], "-h") == 0) || (stricmp (argv[0], "--help") == 0)) {\r
+    Usage();\r
+    return STATUS_SUCCESS;    \r
+  }\r
+\r
+  if ((stricmp (argv[0], "-v") == 0) || (stricmp (argv[0], "--version") == 0)) {\r
+    Version();\r
+    return STATUS_SUCCESS;    \r
+  }\r
+\r
+  while (argc > 0) {\r
+    if ((stricmp (argv[0], "-t") == 0) || (stricmp (argv[0], "--filetype") == 0)) {\r
+      FfsFiletype = StringToType (argv[1]);\r
+      if (FfsFiletype == EFI_FV_FILETYPE_ALL) {\r
+        Error (NULL, 0, 0, NULL, "ERROR: %s is one invalid fv file type", argv[1]);\r
+        goto Finish;      \r
+      }\r
+      argc -= 2;\r
+      argv += 2;\r
+      continue; \r
+    }\r
+\r
+    if ((stricmp (argv[0], "-o") == 0) || (stricmp (argv[0], "--outputfile") == 0)) {\r
+      OutputFileName = argv[1];\r
+      argc -= 2;\r
+      argv += 2;\r
+      continue; \r
+    }\r
+\r
+    if ((stricmp (argv[0], "-g") == 0) || (stricmp (argv[0], "--fileguid") == 0)) {\r
+      Status = StringToGuid (argv[1], &FileGuid);\r
+      if (EFI_ERROR (Status)) {\r
+        Error (NULL, 0, 0, NULL, "ERROR: %s is not correct guid format", argv[1]);\r
+        goto Finish;\r
+      }\r
+      argc -= 2;\r
+      argv += 2;\r
+      continue;\r
+    }\r
+\r
+    if ((stricmp (argv[0], "-x") == 0) || (stricmp (argv[0], "--fixed") == 0)) {\r
+      FfsAttrib |= FFS_ATTRIB_FIXED;\r
+      argc -= 1;\r
+      argv += 1;\r
+      continue;\r
+    }\r
+\r
+    if ((stricmp (argv[0], "-s") == 0) || (stricmp (argv[0], "--checksum") == 0)) {\r
+      FfsAttrib |= FFS_ATTRIB_CHECKSUM;\r
+      argc -= 1;\r
+      argv += 1;\r
+      continue;\r
+    }\r
+\r
+    if ((stricmp (argv[0], "-a") == 0) || (stricmp (argv[0], "--align") == 0)) {\r
+      for (Index = 0; Index < sizeof (mFfsValidAlignName) / sizeof (CHAR8 *); Index ++) {\r
+        if (stricmp (argv[1], mFfsValidAlignName[Index]) == 0) {\r
+          break;\r
+        }\r
+      }\r
+      if (Index == sizeof (mFfsValidAlignName) / sizeof (CHAR8 *)) {\r
+        Error (NULL, 0, 0, NULL, "ERROR: %s is one invalid ffs file alignment", argv[1]);\r
+        goto Finish;\r
+      }\r
+      FfsAlign = Index;\r
+      argc -= 2;\r
+      argv += 2;\r
+      continue;\r
+    }\r
+\r
+    if ((stricmp (argv[0], "-i") == 0) || (stricmp (argv[0], "--sectionfile") == 0)) {\r
+      //\r
+      // Get Input file name and its alignment\r
+      //\r
+      \r
+      //\r
+      // Allocate Input file name buffer and its alignment buffer.\r
+      //\r
+      if ((InputFileNum == 0) && (InputFileName == NULL)) {\r
+        InputFileName = (CHAR8 **) malloc (MAXIMUM_INPUT_FILE_NUM * sizeof (CHAR8 *));\r
+        if (InputFileName == NULL) {\r
+          Error (__FILE__, __LINE__, 0, "application error", "failed to allocate memory");\r
+          return EFI_OUT_OF_RESOURCES;\r
+        }\r
+        memset (InputFileName, 0, (MAXIMUM_INPUT_FILE_NUM * sizeof (CHAR8 *)));\r
+        \r
+        InputFileAlign = (UINT32 *) malloc (MAXIMUM_INPUT_FILE_NUM * sizeof (UINT32));\r
+        if (InputFileAlign == NULL) {\r
+          Error (__FILE__, __LINE__, 0, "application error", "failed to allocate memory");\r
+          free (InputFileName);\r
+          return EFI_OUT_OF_RESOURCES;\r
+        }\r
+        memset (InputFileAlign, 0, MAXIMUM_INPUT_FILE_NUM * sizeof (UINT32));\r
+      } else if (InputFileNum % MAXIMUM_INPUT_FILE_NUM == 0) {\r
+        //\r
+        // InputFileName and alignment buffer too small, need to realloc\r
+        //\r
+        InputFileName = (CHAR8 **) realloc (\r
+                                    InputFileName,\r
+                                    (InputFileNum + MAXIMUM_INPUT_FILE_NUM) * sizeof (CHAR8 *)\r
+                                    );\r
+  \r
+        if (InputFileName == NULL) {\r
+          Error (__FILE__, __LINE__, 0, "application error", "failed to allocate memory");\r
+          free (InputFileAlign);\r
+          return EFI_OUT_OF_RESOURCES;\r
+        }\r
+        memset (&(InputFileName[InputFileNum]), 0, (MAXIMUM_INPUT_FILE_NUM * sizeof (CHAR8 *)));\r
+\r
+        InputFileAlign = (UINT32 *) realloc (\r
+                                    InputFileAlign,\r
+                                    (InputFileNum + MAXIMUM_INPUT_FILE_NUM) * sizeof (UINT32)\r
+                                    );\r
+  \r
+        if (InputFileAlign == NULL) {\r
+          Error (__FILE__, __LINE__, 0, "application error", "failed to allocate memory");\r
+          free (InputFileName);\r
+          return EFI_OUT_OF_RESOURCES;\r
+        }\r
+        memset (&(InputFileAlign[InputFileNum]), 0, (MAXIMUM_INPUT_FILE_NUM * sizeof (UINT32)));\r
+      }\r
+  \r
+      InputFileName[InputFileNum] = argv[1];\r
+      argc -= 2;\r
+      argv += 2;\r
+\r
+      if (argc <= 0) {\r
+           InputFileNum ++;\r
+        break;\r
+      }\r
+\r
+      if ((stricmp (argv[0], "-n") == 0) || (stricmp (argv[0], "--sectionalign") == 0)) {\r
+        Status = StringtoAlignment (argv[1], &(InputFileAlign[InputFileNum]));\r
+        if (EFI_ERROR (Status)) {\r
+          Error (NULL, 0, 0, NULL, "ERROR: %s is invalid alignment", argv[1]);\r
+          goto Finish;\r
+        }\r
+        argc -= 2;\r
+        argv += 2;\r
+      }\r
+      InputFileNum ++;\r
+      continue; \r
+    }\r
+\r
+    if ((stricmp (argv[0], "-n") == 0) || (stricmp (argv[0], "--sectionalign") == 0)) {\r
+      Error (NULL, 0, 0, NULL, "ERROR: SectionAlign much be specified with section file");\r
+      goto Finish;\r
+    }\r
+    \r
+    Error (NULL, 0, 0, NULL, "%s is invaild paramter!", argv[0]);\r
+    goto Finish;\r
+  }\r
+\r
+  if (CompareGuid (&FileGuid, &mZeroGuid) == 0) {\r
+    Error (NULL, 0, 0, NULL, "File Guid value is not specified");\r
+    goto Finish;    \r
+  }\r
+\r
+  if (InputFileNum == 0) {\r
+    Error (NULL, 0, 0, NULL, "ERROR: No input section files");\r
+    goto Finish;\r
+  }\r
+\r
+  //\r
+  // Calculate the size of all input section files.\r
+  //  \r
+  Status = GetSectionContents (\r
+             InputFileName,\r
+             InputFileAlign,\r
+             InputFileNum,\r
+             FileBuffer,\r
+             &FileSize,\r
+             &MaxAlignment\r
+             );\r
+\r
+  if (Status == EFI_BUFFER_TOO_SMALL) {\r
+    FileBuffer = (UINT8 *) malloc (FileSize);\r
+    if (FileBuffer == NULL) {\r
+      Error (__FILE__, __LINE__, 0, "application error", "failed to allocate memory");\r
+      goto Finish;\r
+    }\r
+    memset (FileBuffer, 0, FileSize);\r
+    \r
+    //\r
+    // read all input file contents into a buffer\r
+    //\r
+    Status = GetSectionContents (\r
+               InputFileName,\r
+               InputFileAlign,\r
+               InputFileNum,\r
+               FileBuffer,\r
+               &FileSize,\r
+               &MaxAlignment\r
+               );\r
+  }\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    goto Finish;\r
+  }\r
+  \r
+  //\r
+  // Create Ffs file header.\r
+  //\r
+  memset (&FfsFileHeader, 0, sizeof (EFI_FFS_FILE_HEADER));\r
+  memcpy (&FfsFileHeader.Name, &FileGuid, sizeof (EFI_GUID));\r
+  FfsFileHeader.Type       = FfsFiletype;\r
+  //\r
+  // Update FFS Alignment based on the max alignment required by input section files \r
+  //\r
+  for (Index = 0; Index < sizeof (mFfsValidAlign) / sizeof (UINT32) - 1; Index ++) {\r
+    if ((MaxAlignment > mFfsValidAlign [Index]) && (MaxAlignment <= mFfsValidAlign [Index + 1])) {\r
+      break;\r
+    }\r
+  }\r
+  if (FfsAlign < Index) {\r
+    FfsAlign = Index;\r
+  }\r
+  \r
+  FfsFileHeader.Attributes = FfsAttrib | (FfsAlign << 3);\r
+  \r
+  //\r
+  // Now FileSize includes the EFI_FFS_FILE_HEADER\r
+  //\r
+  FileSize += sizeof (EFI_FFS_FILE_HEADER);\r
+  FfsFileHeader.Size[0]  = (UINT8) (FileSize & 0xFF);\r
+  FfsFileHeader.Size[1]  = (UINT8) ((FileSize & 0xFF00) >> 8);\r
+  FfsFileHeader.Size[2]  = (UINT8) ((FileSize & 0xFF0000) >> 16);\r
+  //\r
+  // Fill in checksums and state, these must be zero for checksumming\r
+  //\r
+  // FileHeader.IntegrityCheck.Checksum.Header = 0;\r
+  // FileHeader.IntegrityCheck.Checksum.File = 0;\r
+  // FileHeader.State = 0;\r
+  //\r
+  FfsFileHeader.IntegrityCheck.Checksum.Header = CalculateChecksum8 (\r
+                                                   (UINT8 *) &FfsFileHeader,\r
+                                                   sizeof (EFI_FFS_FILE_HEADER)\r
+                                                   );\r
+  if (FfsFileHeader.Attributes & FFS_ATTRIB_CHECKSUM) {\r
+    //\r
+    // Ffs header checksum = zero, so only need to calculate ffs body.\r
+    //\r
+    FfsFileHeader.IntegrityCheck.Checksum.File = CalculateChecksum8 (\r
+                                                   FileBuffer, \r
+                                                   FileSize - sizeof (EFI_FFS_FILE_HEADER)\r
+                                                   );    \r
+  } else {\r
+    FfsFileHeader.IntegrityCheck.Checksum.File = FFS_FIXED_CHECKSUM;\r
+  }\r
+\r
+  FfsFileHeader.State = EFI_FILE_HEADER_CONSTRUCTION | EFI_FILE_HEADER_VALID | EFI_FILE_DATA_VALID;\r
+  \r
+  //\r
+  // Open output file to write ffs data.\r
+  //\r
+  if (OutputFileName == NULL) {\r
+    FfsFile = stdout;\r
+  } else {\r
+    FfsFile = fopen (OutputFileName, "wb");\r
+  }\r
+  if (FfsFile == NULL) {\r
+    Error (NULL, 0, 0, NULL, "Can't open %s file to write!", OutputFileName);\r
+    goto Finish;\r
+  }\r
+  //\r
+  // write header\r
+  //\r
+  fwrite (&FfsFileHeader, 1, sizeof (FfsFileHeader), FfsFile);\r
+  //\r
+  // write data\r
+  //\r
+  fwrite (FileBuffer, 1, FileSize - sizeof (EFI_FFS_FILE_HEADER), FfsFile);\r
+\r
+  fclose (FfsFile);\r
+\r
+Finish:\r
+  if (InputFileName != NULL) {\r
+    free (InputFileName);\r
+  }\r
+  if (InputFileAlign != NULL) {\r
+    free (InputFileAlign);\r
+  }\r
+  if (FileBuffer != NULL) {\r
+    free (FileBuffer);\r
+  }\r
+  //\r
+  // If any errors were reported via the standard error reporting\r
+  // routines, then the status has been saved. Get the value and\r
+  // return it to the caller.\r
+  //\r
+  return GetUtilityStatus ();\r
+}\r
diff --git a/Source/C/GenFfs/Makefile b/Source/C/GenFfs/Makefile
new file mode 100644 (file)
index 0000000..1de2d48
--- /dev/null
@@ -0,0 +1,10 @@
+!INCLUDE ..\MSmakefile.common
+
+APPNAME = GenFfs
+
+LIBS = Common.lib
+
+OBJECTS = GenFfs.obj
+
+!INCLUDE ..\MSmakefile.app
+
index 077361a..1dd2447 100644 (file)
@@ -65,7 +65,7 @@ Returns:
 \r
 --*/\r
 {\r
-  printf ("%s v%d.%d -Tiano Firmware Volume Generation Utility.\n", UTILITY_NAME, UTILITY_MAJOR_VERSION, UTILITY_MINOR_VERSION);\r
+  printf ("%s v%d.%d - EDKII Firmware Volume Generation Utility.\n", UTILITY_NAME, UTILITY_MAJOR_VERSION, UTILITY_MINOR_VERSION);\r
   printf ("Copyright (c) 2007 Intel Corporation. All rights reserved.\n");\r
 }\r
  \r
@@ -137,7 +137,7 @@ Returns:
   UINTN       InfFileSize;\r
   CHAR8       *FvFileName;\r
   EFI_PHYSICAL_ADDRESS XipBase;\r
-  \r
+\r
   InfFileName   = NULL;\r
   InfFileImage  = NULL;\r
   FvFileName    = NULL;\r
@@ -170,6 +170,9 @@ Returns:
   while (argc > 0) {\r
     if ((stricmp (argv[0], "-i") == 0) || (stricmp (argv[0], "--inputfile") == 0)) {\r
       InfFileName = argv[1];\r
+      if (InfFileName == NULL) {\r
+        Warning (NULL, 0, 0, NULL, "No input file specified.");\r
+      }\r
       argc -= 2;\r
       argv += 2;\r
       continue; \r
@@ -177,6 +180,9 @@ Returns:
 \r
     if ((stricmp (argv[0], "-o") == 0) || (stricmp (argv[0], "--outputfile") == 0)) {\r
       FvFileName = argv[1];\r
+      if (FvFileName == NULL) {\r
+        Warning (NULL, 0, 0, NULL, "No output file specified.");\r
+      }\r
       argc -= 2;\r
       argv += 2;\r
       continue; \r
@@ -192,6 +198,12 @@ Returns:
       argv += 2;\r
       continue; \r
     }\r
+    \r
+    //\r
+    // Don't recognize the paramter.\r
+    //\r
+    Error (NULL, 0, 0, NULL, "%s is invaild paramter!", argv[0]);\r
+    return STATUS_ERROR;\r
   }\r
 \r
   //\r
@@ -203,7 +215,7 @@ Returns:
   }\r
 \r
   //\r
-  // Call the GenFvImage lib to generate Fv Image\r
+  // Call the GenFvImageFunction to generate Fv Image\r
   //\r
   Status = GenerateFvImage (\r
             InfFileImage,\r
index 566eade..a71134d 100644 (file)
@@ -34,20 +34,58 @@ Abstract:
 #include <assert.h>\r
 \r
 #include <Common/UefiBaseTypes.h>\r
-#include <Common/Variable.h>\r
-#include <Common/WorkingBlockHeader.h>\r
-\r
 #include "GenFvInternalLib.h"\r
 #include "CommonLib.h"\r
-#include "Crc32.h"\r
 #include "EfiUtilityMsgs.h"\r
-#include "Compress.h"\r
 #include "WinNtInclude.h"\r
 \r
 EFI_STATUS\r
 CalculateFvSize (\r
   FV_INFO *FvInfoPtr\r
   );\r
+/*++\r
+Routine Description:\r
+  Calculate the FV size and Update Fv Size based on the actual FFS files.\r
+  And Update FvInfo data.\r
+\r
+Arguments:\r
+  FvInfoPtr     - The pointer to FV_INFO structure.\r
+\r
+Returns:\r
+  EFI_ABORTED   - Ffs Image Error\r
+  EFI_SUCCESS   - Successfully update FvSize\r
+--*/\r
+\r
+EFI_STATUS\r
+FfsRebase ( \r
+  IN OUT  FV_INFO               *FvInfo, \r
+  IN      CHAR8                 *FileName,           \r
+  IN OUT  EFI_FFS_FILE_HEADER   *FfsFile,\r
+  IN      UINTN                 XipOffset\r
+  );\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  This function determines if a file is XIP and should be rebased.  It will\r
+  rebase any PE32 sections found in the file using the base address.\r
+\r
+Arguments:\r
+  \r
+  FvInfo            A pointer to FV_INFO struture.\r
+  FileName          Ffs file Name\r
+  FfsFile           A pointer to Ffs file image.\r
+  XipOffset         The offset address to use for rebasing the XIP file image.\r
+\r
+Returns:\r
+\r
+  EFI_SUCCESS             The image was properly rebased.\r
+  EFI_INVALID_PARAMETER   An input parameter is invalid.\r
+  EFI_ABORTED             An error occurred while rebasing the input file image.\r
+  EFI_OUT_OF_RESOURCES    Could not allocate a required resource.\r
+  EFI_NOT_FOUND           No compressed sections could be found.\r
+\r
+--*/\r
 \r
 static UINT32 MaxFfsAlignment = 0;\r
 \r
@@ -730,7 +768,7 @@ Returns:
   // Done with the file, from this point on we will just use the buffer read.\r
   //\r
   fclose (NewFile);\r
-\r
+  \r
   //\r
   // Verify read successful\r
   //\r
@@ -739,6 +777,16 @@ Returns:
     Error (NULL, 0, 0, FvInfo->FvFiles[Index], "failed to read input file contents");\r
     return EFI_ABORTED;\r
   }\r
+  \r
+  //\r
+  // Verify Ffs file\r
+  //\r
+  Status = VerifyFfsFile (FileBuffer);\r
+  if (EFI_ERROR (Status)) {\r
+    Error (NULL, 0, 0, FvInfo->FvFiles[Index], "the invalid FFS file");\r
+    free (FileBuffer);\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
 \r
   //\r
   // Verify space exists to add the file\r
@@ -768,7 +816,7 @@ Returns:
   if (CurrentFileAlignment > MaxFfsAlignment) {\r
     MaxFfsAlignment = CurrentFileAlignment;\r
   }\r
-\r
+  _asm int 3;\r
   //\r
   // If we have a VTF file, add it at the top.\r
   //\r
@@ -781,13 +829,16 @@ Returns:
       //\r
       // Sanity check. The file MUST align appropriately\r
       //\r
-      \r
       if (((UINTN) *VtfFileImage + sizeof (EFI_FFS_FILE_HEADER) - (UINTN) FvImage->FileImage) % (1 << CurrentFileAlignment)) {\r
         Error (NULL, 0, 0, NULL, "VTF file does not align on %d-byte boundary", 1 << CurrentFileAlignment);\r
         free (FileBuffer);\r
         return EFI_ABORTED;\r
       }\r
-\r
+      //\r
+      // Rebase the PE or TE image in FileBuffer of FFS file for XIP \r
+      // Rebase for the debug genfvmap tool\r
+      //\r
+      FfsRebase (FvInfo, FvInfo->FvFiles[Index], (EFI_FFS_FILE_HEADER *) FileBuffer, (UINTN) *VtfFileImage - (UINTN) FvImage->FileImage);\r
       //\r
       // copy VTF File\r
       //\r
@@ -818,16 +869,14 @@ Returns:
   //\r
   if ((FvImage->CurrentFilePointer + FileSize) < FvImage->Eof) {\r
     //\r
-    // Copy the file\r
+    // Rebase the PE or TE image in FileBuffer of FFS file for XIP. \r
+    // Rebase Bs and Rt drivers for the debug genfvmap tool.\r
     //\r
-    memcpy (FvImage->CurrentFilePointer, FileBuffer, FileSize);\r
-\r
-    //\r
-    // If the file is XIP, rebase To do\r
+    FfsRebase (FvInfo, FvInfo->FvFiles[Index], (EFI_FFS_FILE_HEADER *) FileBuffer, (UINTN) FvImage->CurrentFilePointer - (UINTN) FvImage->FileImage);\r
     //\r
-    // CurrentFileBaseAddress = FvInfo->BaseAddress + ((UINTN) FvImage->CurrentFilePointer - (UINTN) FvImage->FileImage);\r
+    // Copy the file\r
     //\r
-\r
+    memcpy (FvImage->CurrentFilePointer, FileBuffer, FileSize);\r
     FvImage->CurrentFilePointer += FileSize;\r
   } else {\r
     Error (NULL, 0, 0, NULL, "ERROR: The firmware volume is out of space, could not add file %s.\n", FvInfo->FvFiles[Index]);\r
@@ -840,6 +889,7 @@ Returns:
   while (((UINTN) FvImage->CurrentFilePointer & (EFI_FFS_FILE_HEADER_ALIGNMENT - 1)) != 0) {\r
     FvImage->CurrentFilePointer++;\r
   }\r
+\r
   //\r
   // Free allocated memory.\r
   //\r
@@ -882,9 +932,10 @@ Returns:
   // pad file, then there's nothing to do\r
   //\r
   if ((UINTN) VtfFileImage == (UINTN) FvImage->Eof || \\r
-      ((UINTN) FvImage->CurrentFilePointer - (UINTN) VtfFileImage) <= sizeof (EFI_FFS_FILE_HEADER)) {\r
+      ((UINTN) VtfFileImage == (UINTN) FvImage->CurrentFilePointer)) {\r
     return EFI_SUCCESS;\r
   }\r
+\r
   //\r
   // Pad file starts at beginning of free space\r
   //\r
@@ -1346,6 +1397,8 @@ Returns:
   UINTN                       FvImageSize;\r
   FILE                        *FvFile;\r
 \r
+  FvBufferHeader = NULL;\r
+  FvFile         = NULL;\r
   //\r
   // Check for invalid parameter\r
   //\r
@@ -1366,18 +1419,18 @@ Returns:
   Status = ParseFvInf (&InfMemoryFile, &FvInfo);\r
   if (EFI_ERROR (Status)) {\r
     Error (NULL, 0, 0, NULL, "ERROR: Could not parse the input INF file.");\r
-    return EFI_ABORTED;\r
+    return Status;\r
   }\r
 \r
   //\r
   // Update the file name return values\r
   //\r
-  if (FvFileName == NULL && FvInfo.FvName != NULL) {\r
+  if (FvFileName == NULL && FvInfo.FvName[0] != '\0') {\r
     FvFileName = FvInfo.FvName;\r
   }\r
   \r
   //\r
-  // Update FvImage Base Address\r
+  // Update FvImage Base Address, XipBase not same to BtBase, RtBase address.\r
   //\r
   if (XipBaseAddress != -1) {\r
     FvInfo.BaseAddress = XipBaseAddress;\r
@@ -1389,7 +1442,7 @@ Returns:
   //\r
   Status = CalculateFvSize (&FvInfo);\r
   if (EFI_ERROR (Status)) {\r
-    return EFI_ABORTED;    \r
+    return Status;    \r
   }\r
   \r
   //\r
@@ -1400,7 +1453,7 @@ Returns:
   //\r
   // Allocate the FV, assure FvImage Header 8 byte alignment\r
   //\r
-  FvBufferHeader = malloc (FvInfo.Size + 8);\r
+  FvBufferHeader = malloc (FvImageSize + 8);\r
   if (FvBufferHeader == NULL) {\r
     return EFI_OUT_OF_RESOURCES;\r
   }\r
@@ -1440,7 +1493,7 @@ Returns:
   //\r
   // Copy firmware block map\r
   //\r
-  for (Index = 0; FvInfo.FvBlocks[Index].NumBlocks != 0; Index++) {\r
+  for (Index = 0; FvInfo.FvBlocks[Index].Length != 0; Index++) {\r
     FvHeader->BlockMap[Index].NumBlocks   = FvInfo.FvBlocks[Index].NumBlocks;\r
     FvHeader->BlockMap[Index].Length      = FvInfo.FvBlocks[Index].Length;\r
   }\r
@@ -1475,7 +1528,7 @@ Returns:
   //\r
   // Initialize the FV library.\r
   //\r
-  InitializeFvLib (FvImageMemoryFile.FileImage, FvInfo.Size);\r
+  InitializeFvLib (FvImageMemoryFile.FileImage, FvImageSize);\r
 \r
   //\r
   // Initialize the VTF file address.\r
@@ -1496,8 +1549,7 @@ Returns:
     //\r
     if (EFI_ERROR (Status)) {\r
       Error (NULL, 0, 0, NULL, "ERROR: Could not add file %s.", FvInfo.FvFiles[Index]);\r
-      free (FvBufferHeader);\r
-      return EFI_ABORTED;\r
+      goto Finish;\r
     }\r
   }\r
 \r
@@ -1507,12 +1559,12 @@ Returns:
   if ((UINTN) VtfFileImage != (UINTN) FvImageMemoryFile.Eof) {\r
     //\r
     // Pad from the end of the last file to the beginning of the VTF file.\r
+    // If the left space is less than sizeof (EFI_FFS_FILE_HEADER)?\r
     //\r
     Status = PadFvImage (&FvImageMemoryFile, VtfFileImage);\r
     if (EFI_ERROR (Status)) {\r
       Error (NULL, 0, 0, NULL, "ERROR: Could not create the pad file between the last file and the VTF file.");\r
-      free (FvBufferHeader);\r
-      return EFI_ABORTED;\r
+      goto Finish;\r
     }\r
     //\r
     // Update reset vector (SALE_ENTRY for IPF)\r
@@ -1524,9 +1576,8 @@ Returns:
     if ((FvInfo.BaseAddress + FvInfo.Size) == FV_IMAGES_TOP_ADDRESS) {       \r
       Status = UpdateResetVector (&FvImageMemoryFile, &FvInfo, VtfFileImage);\r
       if (EFI_ERROR(Status)) {                                               \r
-        Error (NULL, 0, 0, NULL, "ERROR: Could not update the reset vector.");              \r
-        free (FvBufferHeader);                                                     \r
-        return EFI_ABORTED;                                                  \r
+        Error (NULL, 0, 0, NULL, "ERROR: Could not update the reset vector.");\r
+        goto Finish;                                              \r
       }\r
     }\r
   } \r
@@ -1543,12 +1594,6 @@ Returns:
     FvHeader->Checksum      = CalculateChecksum16 ((UINT16 *) FvHeader, FvHeader->HeaderLength / sizeof (UINT16));\r
   }\r
 \r
-  if (XipBaseAddress != -1) {\r
-    //\r
-    // Rebase Fv Image\r
-    //\r
-  }\r
-\r
 WriteFile: \r
   //\r
   // Write fv file\r
@@ -1561,21 +1606,26 @@ WriteFile:
 \r
   if (FvFile == NULL) {\r
     Error (NULL, 0, 0, FvFileName, "could not open output file");\r
-    free (FvBufferHeader);\r
-    return EFI_ABORTED;\r
+    Status = EFI_ABORTED;\r
+    goto Finish;\r
   }\r
 \r
   if (fwrite (FvImage, 1, FvImageSize, FvFile) != FvImageSize) {\r
     Error (NULL, 0, 0, FvFileName, "failed to write to output file");\r
+    Status = EFI_ABORTED;\r
+    goto Finish;\r
+  }\r
+\r
+Finish:\r
+  if (FvBufferHeader != NULL) {\r
     free (FvBufferHeader);\r
+  }\r
+  \r
+  if (FvFile != NULL) {\r
     fclose (FvFile);\r
-    return EFI_ABORTED;\r
   }\r
 \r
-  free (FvBufferHeader);\r
-  fclose (FvFile);\r
-\r
-  return EFI_SUCCESS;\r
+  return Status;\r
 }\r
 \r
 EFI_STATUS\r
@@ -1652,6 +1702,18 @@ EFI_STATUS
 CalculateFvSize (\r
   FV_INFO *FvInfoPtr\r
   )\r
+/*++\r
+Routine Description:\r
+  Calculate the FV size and Update Fv Size based on the actual FFS files.\r
+  And Update FvInfo data.\r
+\r
+Arguments:\r
+  FvInfoPtr     - The pointer to FV_INFO structure.\r
+\r
+Returns:\r
+  EFI_ABORTED   - Ffs Image Error\r
+  EFI_SUCCESS   - Successfully update FvSize\r
+--*/\r
 {\r
   UINTN               CurrentOffset;\r
   UINTN               Index;\r
@@ -1710,6 +1772,11 @@ CalculateFvSize (
         return EFI_ABORTED;\r
       }\r
       VtfFileFlag = TRUE;\r
+      //\r
+      // The space between Vft File and the latest file must be able to contain \r
+      // one ffs file header in order to add one pad file.\r
+      //\r
+      CurrentOffset += sizeof (EFI_FFS_FILE_HEADER);\r
     }\r
     //\r
     // Get the alignment of FFS file \r
@@ -1744,4 +1811,350 @@ CalculateFvSize (
   }\r
 \r
   return EFI_SUCCESS;\r
-}    
\ No newline at end of file
+}\r
+\r
+EFI_STATUS\r
+FfsRebaseImageRead (\r
+  IN     VOID    *FileHandle,\r
+  IN     UINTN   FileOffset,\r
+  IN OUT UINT32  *ReadSize,\r
+  OUT    VOID    *Buffer\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Support routine for the PE/COFF Loader that reads a buffer from a PE/COFF file\r
+\r
+Arguments:\r
+\r
+  FileHandle - The handle to the PE/COFF file\r
+\r
+  FileOffset - The offset, in bytes, into the file to read\r
+\r
+  ReadSize   - The number of bytes to read from the file starting at FileOffset\r
+\r
+  Buffer     - A pointer to the buffer to read the data into.\r
+\r
+Returns:\r
+\r
+  EFI_SUCCESS - ReadSize bytes of data were read into Buffer from the PE/COFF file starting at FileOffset\r
+\r
+--*/\r
+{\r
+  CHAR8   *Destination8;\r
+  CHAR8   *Source8;\r
+  UINT32  Length;\r
+\r
+  Destination8  = Buffer;\r
+  Source8       = (CHAR8 *) ((UINTN) FileHandle + FileOffset);\r
+  Length        = *ReadSize;\r
+  while (Length--) {\r
+    *(Destination8++) = *(Source8++);\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+FfsRebase ( \r
+  IN OUT  FV_INFO               *FvInfo, \r
+  IN      CHAR8                 *FileName,           \r
+  IN OUT  EFI_FFS_FILE_HEADER   *FfsFile,\r
+  IN      UINTN                 XipOffset\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  This function determines if a file is XIP and should be rebased.  It will\r
+  rebase any PE32 sections found in the file using the base address.\r
+\r
+Arguments:\r
+  \r
+  FvInfo            A pointer to FV_INFO struture.\r
+  FfsFile           A pointer to Ffs file image.\r
+  XipOffset         The offset address to use for rebasing the XIP file image.\r
+\r
+Returns:\r
+\r
+  EFI_SUCCESS             The image was properly rebased.\r
+  EFI_INVALID_PARAMETER   An input parameter is invalid.\r
+  EFI_ABORTED             An error occurred while rebasing the input file image.\r
+  EFI_OUT_OF_RESOURCES    Could not allocate a required resource.\r
+  EFI_NOT_FOUND           No compressed sections could be found.\r
+\r
+--*/\r
+{\r
+  EFI_STATUS                            Status;\r
+  PE_COFF_LOADER_IMAGE_CONTEXT          ImageContext;\r
+  EFI_PHYSICAL_ADDRESS                  XipBase;\r
+  EFI_PHYSICAL_ADDRESS                  NewPe32BaseAddress;\r
+  EFI_PHYSICAL_ADDRESS                  *BaseToUpdate;\r
+  UINTN                                 Index;\r
+  EFI_FILE_SECTION_POINTER              CurrentPe32Section;\r
+  EFI_FFS_FILE_STATE                    SavedState;\r
+  EFI_IMAGE_NT_HEADERS32                *PeHdr;\r
+  EFI_TE_IMAGE_HEADER                   *TEImageHeader;\r
+  UINT8                                 Flags;\r
+  \r
+  //\r
+  // Check XipAddress, BootAddress and RuntimeAddress\r
+  //\r
+  Flags = 0;\r
+  if (FvInfo->BaseAddress != -1) {\r
+    Flags  |= REBASE_XIP_FILE;\r
+    XipBase = FvInfo->BaseAddress + XipOffset;\r
+  }\r
+  if (FvInfo->BootBaseAddress != 0) {\r
+    Flags  |= REBASE_BOOTTIME_FILE;\r
+  }\r
+  if (FvInfo->RuntimeBaseAddress != 0) {\r
+    Flags  |= REBASE_RUNTIME_FILE;\r
+  }\r
+  //\r
+  // Don't Rebase this FFS.\r
+  //\r
+  if (Flags == 0) {\r
+    return EFI_SUCCESS;\r
+  }\r
+\r
+  //\r
+  // We only process files potentially containing PE32 sections.\r
+  //\r
+  switch (FfsFile->Type) {\r
+    case EFI_FV_FILETYPE_SECURITY_CORE:\r
+    case EFI_FV_FILETYPE_PEI_CORE:\r
+    case EFI_FV_FILETYPE_PEIM:\r
+    case EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER:\r
+    case EFI_FV_FILETYPE_DRIVER:\r
+    case EFI_FV_FILETYPE_DXE_CORE:\r
+      break;\r
+    default:\r
+      return EFI_SUCCESS;\r
+  }\r
+\r
+  //\r
+  // Rebase each PE32 section\r
+  //\r
+  Status      = EFI_SUCCESS;\r
+  for (Index = 1;; Index++) {\r
+    Status = GetSectionByType (FfsFile, EFI_SECTION_PE32, Index, &CurrentPe32Section);\r
+    if (EFI_ERROR (Status)) {\r
+      break;\r
+    }\r
+\r
+    //\r
+    // Initialize context\r
+    //\r
+    memset (&ImageContext, 0, sizeof (ImageContext));\r
+    ImageContext.Handle     = (VOID *) ((UINTN) CurrentPe32Section.Pe32Section + sizeof (EFI_PE32_SECTION));\r
+    ImageContext.ImageRead  = (PE_COFF_LOADER_READ_FILE) FfsRebaseImageRead;\r
+    Status                  = PeCoffLoaderGetImageInfo (&ImageContext);\r
+    if (EFI_ERROR (Status)) {\r
+      Error (NULL, 0, 0, "GetImageInfo() call failed on rebase", FileName);\r
+      return Status;\r
+    }\r
+\r
+    //\r
+    // Don't Load PeImage, only to relocate current image.\r
+    //\r
+    ImageContext.ImageAddress = (UINTN) CurrentPe32Section.Pe32Section + sizeof (EFI_PE32_SECTION);\r
+\r
+    //\r
+    // Check if section-alignment and file-alignment match or not\r
+    //\r
+    PeHdr = (EFI_IMAGE_NT_HEADERS *)((UINTN)ImageContext.ImageAddress + ImageContext.PeCoffHeaderOffset);\r
+    if ((PeHdr->OptionalHeader.SectionAlignment != PeHdr->OptionalHeader.FileAlignment)) {\r
+      //\r
+      // Nor XIP module can be ignored. Todo\r
+      //\r
+      if ((Flags & REBASE_XIP_FILE) == 0) {\r
+        continue;\r
+      }\r
+      Error (NULL, 0, 0, "Section-Alignment and File-Alignment does not match", FileName);\r
+      return EFI_ABORTED;\r
+    }\r
+\r
+    //\r
+    // Calculate the PE32 base address, based on file type\r
+    //\r
+    switch (FfsFile->Type) {\r
+      case EFI_FV_FILETYPE_SECURITY_CORE:\r
+      case EFI_FV_FILETYPE_PEI_CORE:\r
+      case EFI_FV_FILETYPE_PEIM:\r
+      case EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER:\r
+        if ((Flags & REBASE_XIP_FILE) == 0) {\r
+          //\r
+          // We aren't relocating XIP code, so skip it.\r
+          //\r
+          return EFI_SUCCESS;\r
+        }\r
+\r
+        NewPe32BaseAddress =\r
+          XipBase + (UINTN)ImageContext.ImageAddress - (UINTN)FfsFile;\r
+        BaseToUpdate = &XipBase;\r
+        break;\r
+\r
+      case EFI_FV_FILETYPE_DRIVER:\r
+        PeHdr = (EFI_IMAGE_NT_HEADERS32*)(ImageContext.ImageAddress + ImageContext.PeCoffHeaderOffset);\r
+        switch (PeHdr->OptionalHeader.Subsystem) {\r
+          case EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER:\r
+            if ((Flags & REBASE_RUNTIME_FILE) == 0) {\r
+              //\r
+              // RT drivers aren't supposed to be relocated\r
+              //\r
+              continue;\r
+            }\r
+\r
+            NewPe32BaseAddress = FvInfo->RuntimeBaseAddress;\r
+            BaseToUpdate = &(FvInfo->RuntimeBaseAddress);\r
+            break;\r
+\r
+          default:\r
+            //\r
+            // We treat all other subsystems the same as BS_DRIVER\r
+            //\r
+            if ((Flags & REBASE_BOOTTIME_FILE) == 0) {\r
+              //\r
+              // Skip all BS_DRIVER's\r
+              //\r
+              continue;\r
+            }\r
+\r
+            NewPe32BaseAddress = FvInfo->BootBaseAddress;\r
+            BaseToUpdate = &(FvInfo->BootBaseAddress);\r
+            break;\r
+        }\r
+        break;\r
+\r
+      case EFI_FV_FILETYPE_DXE_CORE:\r
+        if ((Flags & REBASE_BOOTTIME_FILE) == 0) {\r
+          //\r
+          // Skip DXE core, DxeCore only contain one PE image.\r
+          //\r
+          return EFI_SUCCESS;\r
+        }\r
+\r
+        NewPe32BaseAddress = FvInfo->BootBaseAddress;\r
+        BaseToUpdate = &(FvInfo->BootBaseAddress);\r
+        break;\r
+\r
+      default:\r
+        //\r
+        // Not supported file type\r
+        //\r
+        return EFI_SUCCESS;\r
+    }\r
+\r
+    ImageContext.DestinationAddress = NewPe32BaseAddress;\r
+    Status                          = PeCoffLoaderRelocateImage (&ImageContext);\r
+    if (EFI_ERROR (Status)) {\r
+      Error (NULL, 0, 0, "RelocateImage() call failed on rebase", FileName);\r
+      return Status;\r
+    }\r
+\r
+    //\r
+    // Update BASE address\r
+    //\r
+    *BaseToUpdate += EFI_SIZE_TO_PAGES (ImageContext.ImageSize) * EFI_PAGE_SIZE;\r
+\r
+    //\r
+    // Now update file checksum\r
+    //\r
+    if (FfsFile->Attributes & FFS_ATTRIB_CHECKSUM) {\r
+      SavedState  = FfsFile->State;\r
+      FfsFile->IntegrityCheck.Checksum.File = 0;\r
+      FfsFile->State                        = 0;\r
+      if (FfsFile->Attributes & FFS_ATTRIB_CHECKSUM) {\r
+        FfsFile->IntegrityCheck.Checksum.File = CalculateChecksum8 (\r
+                                                  (UINT8 *) FfsFile,\r
+                                                  GetLength (FfsFile->Size)\r
+                                                  );\r
+      } else {\r
+        FfsFile->IntegrityCheck.Checksum.File = FFS_FIXED_CHECKSUM;\r
+      }\r
+\r
+      FfsFile->State = SavedState;\r
+    }\r
+  }\r
+\r
+  if ((Flags & 1) == 0 || (\r
+      FfsFile->Type != EFI_FV_FILETYPE_SECURITY_CORE &&\r
+      FfsFile->Type != EFI_FV_FILETYPE_PEI_CORE &&\r
+\r
+      FfsFile->Type != EFI_FV_FILETYPE_PEIM &&\r
+      FfsFile->Type != EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER\r
+      )) {\r
+    //\r
+    // Only XIP code may have a TE section\r
+    //\r
+    return EFI_SUCCESS;\r
+  }\r
+  \r
+  //\r
+  // Now process TE sections\r
+  //\r
+  for (Index = 1;; Index++) {\r
+    Status = GetSectionByType (FfsFile, EFI_SECTION_TE, Index, &CurrentPe32Section);\r
+    if (EFI_ERROR (Status)) {\r
+      break;\r
+    }\r
+\r
+    //\r
+    // Calculate the TE base address, the FFS file base plus the offset of the TE section less the size stripped off\r
+    // by GenTEImage\r
+    //\r
+    TEImageHeader = (EFI_TE_IMAGE_HEADER *) ((UINT8 *) CurrentPe32Section.Pe32Section + sizeof (EFI_COMMON_SECTION_HEADER));\r
+\r
+    //\r
+    // Initialize context, load image info.\r
+    //\r
+    memset (&ImageContext, 0, sizeof (ImageContext));\r
+    ImageContext.Handle     = (VOID *) TEImageHeader;\r
+    ImageContext.ImageRead  = (PE_COFF_LOADER_READ_FILE) FfsRebaseImageRead;\r
+\r
+    Status                  = PeCoffLoaderGetImageInfo (&ImageContext);\r
+\r
+    if (EFI_ERROR (Status)) {\r
+      Error (NULL, 0, 0, "GetImageInfo() call failed on rebase of TE image", FileName);\r
+      return Status;\r
+    }\r
+    //\r
+    // Don't reload TeImage\r
+    //\r
+    ImageContext.ImageAddress = (UINTN) TEImageHeader;\r
+\r
+    //\r
+    // Reloacate TeImage\r
+    // \r
+    ImageContext.DestinationAddress = XipBase + (UINTN) TEImageHeader + sizeof (EFI_TE_IMAGE_HEADER) \\r
+                                      - TEImageHeader->StrippedSize - (UINTN) FfsFile;\r
+    Status                          = PeCoffLoaderRelocateImage (&ImageContext);\r
+    if (EFI_ERROR (Status)) {\r
+      Error (NULL, 0, 0, "RelocateImage() call failed on rebase of TE image", FileName);\r
+      return Status;\r
+    }\r
+\r
+    //\r
+    // Now update file checksum\r
+    //\r
+    if (FfsFile->Attributes & FFS_ATTRIB_CHECKSUM) {\r
+      SavedState  = FfsFile->State;\r
+      FfsFile->IntegrityCheck.Checksum.File = 0;\r
+      FfsFile->State                        = 0;\r
+      if (FfsFile->Attributes & FFS_ATTRIB_CHECKSUM) {\r
+        FfsFile->IntegrityCheck.Checksum.File = CalculateChecksum8 (\r
+                                                  (UINT8 *) FfsFile,\r
+                                                  GetLength (FfsFile->Size)\r
+                                                  );\r
+      } else {\r
+        FfsFile->IntegrityCheck.Checksum.File = FFS_FIXED_CHECKSUM;\r
+      }\r
+\r
+      FfsFile->State = SavedState;\r
+    }\r
+  }\r
\r
+  return EFI_SUCCESS;\r
+}
\ No newline at end of file
index 1d6f91d..842db76 100644 (file)
@@ -37,6 +37,7 @@ Abstract:
 #include <Guid/PiFirmwareFileSystem.h>\r
 \r
 #include <Common/EfiImage.h>\r
+#include <Library/PeCoffLib.h>\r
 \r
 #include "CommonLib.h"\r
 #include "ParseInf.h"\r
@@ -192,6 +193,13 @@ Abstract:
 #define FIT_TYPE_MASK         0x7F\r
 #define CHECKSUM_BIT_MASK     0x80\r
 \r
+//\r
+// Rebase File type\r
+//\r
+#define REBASE_XIP_FILE       0x1\r
+#define REBASE_BOOTTIME_FILE  0x2\r
+#define REBASE_RUNTIME_FILE   0x4\r
+\r
 //\r
 // Private data types\r
 //\r
@@ -208,6 +216,8 @@ typedef struct {
 //\r
 typedef struct {\r
   EFI_PHYSICAL_ADDRESS    BaseAddress;\r
+  EFI_PHYSICAL_ADDRESS    BootBaseAddress;\r
+  EFI_PHYSICAL_ADDRESS    RuntimeBaseAddress;  \r
   EFI_GUID                FvGuid;\r
   UINTN                   Size;\r
   CHAR8                   FvName[_MAX_PATH];\r
index 7ec9844..4ac13cb 100644 (file)
@@ -2,7 +2,7 @@
 
 APPNAME = GenFv
 
-LIBS = Common.lib RpcRT4.lib
+LIBS = Common.lib PeCoffLoader.lib RpcRT4.lib
 
 OBJECTS = GenFv.obj GenFvInternalLib.obj
 
index 897f065..33ba81f 100644 (file)
@@ -108,7 +108,7 @@ Returns:
   \r
 --*/ \r
 {\r
-  printf ("%s v%d.%d -Utility to create output file with formed section per the PI spec.\n", UTILITY_NAME, UTILITY_MAJOR_VERSION, UTILITY_MINOR_VERSION);\r
+  printf ("%s v%d.%d - EDKII Utility to create output file with formed section per the PI spec.\n", UTILITY_NAME, UTILITY_MAJOR_VERSION, UTILITY_MINOR_VERSION);\r
   printf ("Copyright (c) 2007 Intel Corporation. All rights reserved.\n");\r
 }\r
 \r
index 3a18847..95dffd0 100644 (file)
@@ -2,8 +2,8 @@ ARCH = IA32
 
 !INCLUDE MSmakefile.common
 
-LIBRARIES = Common
-APPLICATIONS = GenFw GenSec GenFv
+LIBRARIES = Common PeCoffLoader
+APPLICATIONS = GenFw GenSec GenFv GenFfs
 
 all: libs apps install
 
diff --git a/Source/C/PeCoffLoader/BasePeCoff.c b/Source/C/PeCoffLoader/BasePeCoff.c
new file mode 100644 (file)
index 0000000..3174486
--- /dev/null
@@ -0,0 +1,1100 @@
+/*++\r
+\r
+Copyright (c) 2004 - 2005, Intel Corporation                                                         \r
+All rights reserved. This program and the accompanying materials                          \r
+are licensed and made available under the terms and conditions of the BSD License         \r
+which accompanies this distribution.  The full text of the license may be found at        \r
+http://opensource.org/licenses/bsd-license.php                                            \r
+                                                                                          \r
+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
+  PeCoffLoader.c\r
+\r
+Abstract:\r
+\r
+  Tiano PE/COFF loader \r
+\r
+Revision History\r
+\r
+--*/\r
+\r
+\r
+#include <Common/UefiBaseTypes.h>\r
+#include <Common/EfiImage.h>\r
+#include <Library/PeCoffLib.h>\r
+\r
+STATIC\r
+RETURN_STATUS\r
+PeCoffLoaderGetPeHeader (\r
+  IN OUT PE_COFF_LOADER_IMAGE_CONTEXT  *ImageContext,\r
+  OUT    EFI_IMAGE_NT_HEADERS          *PeHdr,\r
+  OUT    EFI_TE_IMAGE_HEADER           *TeHdr\r
+  );\r
+\r
+STATIC\r
+RETURN_STATUS\r
+PeCoffLoaderCheckImageType (\r
+  IN OUT PE_COFF_LOADER_IMAGE_CONTEXT  *ImageContext,\r
+  IN     EFI_IMAGE_NT_HEADERS          *PeHdr,\r
+  IN     EFI_TE_IMAGE_HEADER           *TeHdr\r
+  );\r
+\r
+STATIC\r
+VOID                            *\r
+PeCoffLoaderImageAddress (\r
+  IN OUT PE_COFF_LOADER_IMAGE_CONTEXT  *ImageContext,\r
+  IN     UINTN                         Address\r
+  );\r
+\r
+RETURN_STATUS\r
+PeCoffLoaderRelocateIa32Image (\r
+  IN UINT16      *Reloc,\r
+  IN OUT CHAR8   *Fixup,\r
+  IN OUT CHAR8   **FixupData,\r
+  IN UINT64      Adjust\r
+  );\r
+\r
+RETURN_STATUS\r
+PeCoffLoaderRelocateX64Image (\r
+  IN UINT16      *Reloc,\r
+  IN OUT CHAR8   *Fixup,\r
+  IN OUT CHAR8   **FixupData,\r
+  IN UINT64      Adjust\r
+  );\r
+\r
+RETURN_STATUS\r
+PeCoffLoaderRelocateIpfImage (\r
+  IN UINT16      *Reloc,\r
+  IN OUT CHAR8   *Fixup,\r
+  IN OUT CHAR8   **FixupData,\r
+  IN UINT64      Adjust\r
+  );\r
+\r
+STATIC\r
+RETURN_STATUS\r
+PeCoffLoaderGetPeHeader (\r
+  IN OUT PE_COFF_LOADER_IMAGE_CONTEXT  *ImageContext,\r
+  OUT    EFI_IMAGE_NT_HEADERS          *PeHdr,\r
+  OUT    EFI_TE_IMAGE_HEADER           *TeHdr\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Retrieves the PE or TE Header from a PE/COFF or TE image\r
+\r
+Arguments:\r
+\r
+  ImageContext  - The context of the image being loaded\r
+\r
+  PeHdr         - The buffer in which to return the PE header\r
+  \r
+  TeHdr         - The buffer in which to return the TE header\r
+\r
+Returns:\r
+\r
+  RETURN_SUCCESS if the PE or TE Header is read, \r
+  Otherwise, the error status from reading the PE/COFF or TE image using the ImageRead function.\r
+\r
+--*/\r
+{\r
+  RETURN_STATUS            Status;\r
+  EFI_IMAGE_DOS_HEADER  DosHdr;\r
+  UINTN                 Size;\r
+\r
+  ImageContext->IsTeImage = FALSE;\r
+  //\r
+  // Read the DOS image headers\r
+  //\r
+  Size = sizeof (EFI_IMAGE_DOS_HEADER);\r
+  Status = ImageContext->ImageRead (\r
+                          ImageContext->Handle,\r
+                          0,\r
+                          &Size,\r
+                          &DosHdr\r
+                          );\r
+  if (RETURN_ERROR (Status)) {\r
+    ImageContext->ImageError = IMAGE_ERROR_IMAGE_READ;\r
+    return Status;\r
+  }\r
+\r
+  ImageContext->PeCoffHeaderOffset = 0;\r
+  if (DosHdr.e_magic == EFI_IMAGE_DOS_SIGNATURE) {\r
+    //\r
+    // DOS image header is present, so read the PE header after the DOS image header\r
+    //\r
+    ImageContext->PeCoffHeaderOffset = DosHdr.e_lfanew;\r
+  }\r
+  //\r
+  // Read the PE/COFF Header\r
+  //\r
+  Size = sizeof (EFI_IMAGE_NT_HEADERS);\r
+  Status = ImageContext->ImageRead (\r
+                          ImageContext->Handle,\r
+                          ImageContext->PeCoffHeaderOffset,\r
+                          &Size,\r
+                          PeHdr\r
+                          );\r
+  if (RETURN_ERROR (Status)) {\r
+    ImageContext->ImageError = IMAGE_ERROR_IMAGE_READ;\r
+    return Status;\r
+  }\r
+  //\r
+  // Check the PE/COFF Header Signature. If not, then try to read a TE header\r
+  //\r
+  if (PeHdr->Signature != EFI_IMAGE_NT_SIGNATURE) {\r
+    Size = sizeof (EFI_TE_IMAGE_HEADER);\r
+    Status = ImageContext->ImageRead (\r
+                            ImageContext->Handle,\r
+                            0,\r
+                            &Size,\r
+                            TeHdr\r
+                            );\r
+    if (TeHdr->Signature != EFI_TE_IMAGE_HEADER_SIGNATURE) {\r
+      return RETURN_UNSUPPORTED;\r
+    }\r
+\r
+    ImageContext->IsTeImage = TRUE;\r
+  }\r
+\r
+  return RETURN_SUCCESS;\r
+}\r
+\r
+STATIC\r
+RETURN_STATUS\r
+PeCoffLoaderCheckImageType (\r
+  IN OUT PE_COFF_LOADER_IMAGE_CONTEXT          *ImageContext,\r
+  IN     EFI_IMAGE_NT_HEADERS                  *PeHdr,\r
+  IN     EFI_TE_IMAGE_HEADER                   *TeHdr\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Checks the PE or TE header of a PE/COFF or TE image to determine if it supported\r
+\r
+Arguments:\r
+\r
+  ImageContext  - The context of the image being loaded\r
+\r
+  PeHdr         - The buffer in which to return the PE header\r
+  \r
+  TeHdr         - The buffer in which to return the TE header\r
+\r
+Returns:\r
+\r
+  RETURN_SUCCESS if the PE/COFF or TE image is supported\r
+  RETURN_UNSUPPORTED of the PE/COFF or TE image is not supported.\r
+\r
+--*/\r
+{\r
+  //\r
+  // See if the machine type is supported.  We support a native machine type (IA-32/Itanium-based)\r
+  // and the machine type for the Virtual Machine.\r
+  //\r
+  if (ImageContext->IsTeImage == FALSE) {\r
+    ImageContext->Machine = PeHdr->FileHeader.Machine;\r
+  } else {\r
+    ImageContext->Machine = TeHdr->Machine;\r
+  }\r
+\r
+  /*\r
+  if (!(EFI_IMAGE_MACHINE_TYPE_SUPPORTED (ImageContext->Machine))) {\r
+    ImageContext->ImageError = IMAGE_ERROR_INVALID_MACHINE_TYPE;\r
+    return RETURN_UNSUPPORTED;\r
+  }\r
+  */\r
+\r
+  //\r
+  // See if the image type is supported.  We support EFI Applications,\r
+  // EFI Boot Service Drivers, and EFI Runtime Drivers.\r
+  //\r
+  if (ImageContext->IsTeImage == FALSE) {\r
+    ImageContext->ImageType = PeHdr->OptionalHeader.Subsystem;\r
+  } else {\r
+    ImageContext->ImageType = (UINT16) (TeHdr->Subsystem);\r
+  }\r
+\r
+\r
+  return RETURN_SUCCESS;\r
+}\r
+\r
+RETURN_STATUS\r
+EFIAPI\r
+PeCoffLoaderGetImageInfo (\r
+  IN OUT PE_COFF_LOADER_IMAGE_CONTEXT           *ImageContext\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Retrieves information on a PE/COFF image\r
+\r
+Arguments:\r
+\r
+  This         - Calling context\r
+  ImageContext - The context of the image being loaded\r
+\r
+Returns:\r
+\r
+  RETURN_SUCCESS           - The information on the PE/COFF image was collected.\r
+  RETURN_INVALID_PARAMETER - ImageContext is NULL.\r
+  RETURN_UNSUPPORTED       - The PE/COFF image is not supported.\r
+  Otherwise             - The error status from reading the PE/COFF image using the\r
+                          ImageContext->ImageRead() function\r
+\r
+--*/\r
+{\r
+  RETURN_STATUS                   Status;\r
+  EFI_IMAGE_NT_HEADERS            PeHdr;\r
+  EFI_TE_IMAGE_HEADER             TeHdr;\r
+  EFI_IMAGE_DATA_DIRECTORY        *DebugDirectoryEntry;\r
+  UINTN                           Size;\r
+  UINTN                           Index;\r
+  UINTN                           DebugDirectoryEntryRva;\r
+  UINTN                           DebugDirectoryEntryFileOffset;\r
+  UINTN                           SectionHeaderOffset;\r
+  EFI_IMAGE_SECTION_HEADER        SectionHeader;\r
+  EFI_IMAGE_DEBUG_DIRECTORY_ENTRY DebugEntry;\r
+\r
+  if (NULL == ImageContext) {\r
+    return RETURN_INVALID_PARAMETER;\r
+  }\r
+  //\r
+  // Assume success\r
+  //\r
+  ImageContext->ImageError  = IMAGE_ERROR_SUCCESS;\r
+\r
+  Status                    = PeCoffLoaderGetPeHeader (ImageContext, &PeHdr, &TeHdr);\r
+  if (RETURN_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+  //\r
+  // Verify machine type\r
+  //\r
+  Status = PeCoffLoaderCheckImageType (ImageContext, &PeHdr, &TeHdr);\r
+  if (RETURN_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+  //\r
+  // Retrieve the base address of the image\r
+  //\r
+  if (!(ImageContext->IsTeImage)) {\r
+    ImageContext->ImageAddress = PeHdr.OptionalHeader.ImageBase;\r
+  } else {\r
+    ImageContext->ImageAddress = (PHYSICAL_ADDRESS) (TeHdr.ImageBase + TeHdr.StrippedSize - sizeof (EFI_TE_IMAGE_HEADER));\r
+  }\r
+  //\r
+  // Initialize the alternate destination address to 0 indicating that it\r
+  // should not be used.\r
+  //\r
+  ImageContext->DestinationAddress = 0;\r
+\r
+  //\r
+  // Initialize the codeview pointer.\r
+  //\r
+  ImageContext->CodeView    = NULL;\r
+  ImageContext->PdbPointer  = NULL;\r
+\r
+  //\r
+  // Three cases with regards to relocations:\r
+  // - Image has base relocs, RELOCS_STRIPPED==0    => image is relocatable\r
+  // - Image has no base relocs, RELOCS_STRIPPED==1 => Image is not relocatable\r
+  // - Image has no base relocs, RELOCS_STRIPPED==0 => Image is relocatable but\r
+  //   has no base relocs to apply\r
+  // Obviously having base relocations with RELOCS_STRIPPED==1 is invalid.\r
+  //\r
+  // Look at the file header to determine if relocations have been stripped, and\r
+  // save this info in the image context for later use.\r
+  //\r
+  if ((!(ImageContext->IsTeImage)) && ((PeHdr.FileHeader.Characteristics & EFI_IMAGE_FILE_RELOCS_STRIPPED) != 0)) {\r
+    ImageContext->RelocationsStripped = TRUE;\r
+  } else {\r
+    ImageContext->RelocationsStripped = FALSE;\r
+  }\r
+\r
+  if (!(ImageContext->IsTeImage)) {\r
+    ImageContext->ImageSize         = (UINT64) PeHdr.OptionalHeader.SizeOfImage;\r
+    ImageContext->SectionAlignment  = PeHdr.OptionalHeader.SectionAlignment;\r
+    ImageContext->SizeOfHeaders     = PeHdr.OptionalHeader.SizeOfHeaders;\r
+\r
+    //\r
+    // Modify ImageSize to contain .PDB file name if required and initialize\r
+    // PdbRVA field...\r
+    //\r
+    if (PeHdr.OptionalHeader.NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_DEBUG) {\r
+      DebugDirectoryEntry = (EFI_IMAGE_DATA_DIRECTORY *) &(PeHdr.OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG]);\r
+\r
+      DebugDirectoryEntryRva = DebugDirectoryEntry->VirtualAddress;\r
+\r
+      //\r
+      // Determine the file offset of the debug directory...  This means we walk\r
+      // the sections to find which section contains the RVA of the debug\r
+      // directory\r
+      //\r
+      DebugDirectoryEntryFileOffset = 0;\r
+\r
+      SectionHeaderOffset = (UINTN)(\r
+                               ImageContext->PeCoffHeaderOffset +\r
+                               sizeof (UINT32) + \r
+                               sizeof (EFI_IMAGE_FILE_HEADER) + \r
+                               PeHdr.FileHeader.SizeOfOptionalHeader\r
+                               );\r
+\r
+      for (Index = 0; Index < PeHdr.FileHeader.NumberOfSections; Index++) {\r
+        //\r
+        // Read section header from file\r
+        //\r
+        Size = sizeof (EFI_IMAGE_SECTION_HEADER);\r
+        Status = ImageContext->ImageRead (\r
+                                 ImageContext->Handle,\r
+                                 SectionHeaderOffset,\r
+                                 &Size,\r
+                                 &SectionHeader\r
+                                 );\r
+        if (RETURN_ERROR (Status)) {\r
+          ImageContext->ImageError = IMAGE_ERROR_IMAGE_READ;\r
+          return Status;\r
+        }\r
+\r
+        if (DebugDirectoryEntryRva >= SectionHeader.VirtualAddress &&\r
+            DebugDirectoryEntryRva < SectionHeader.VirtualAddress + SectionHeader.Misc.VirtualSize) {\r
+            DebugDirectoryEntryFileOffset =\r
+            DebugDirectoryEntryRva - SectionHeader.VirtualAddress + SectionHeader.PointerToRawData;\r
+          break;\r
+        }\r
+\r
+        SectionHeaderOffset += sizeof (EFI_IMAGE_SECTION_HEADER);\r
+      }\r
+\r
+      if (DebugDirectoryEntryFileOffset != 0) {    \r
+        for (Index = 0; Index < DebugDirectoryEntry->Size; Index += sizeof (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY)) {\r
+          //\r
+          // Read next debug directory entry\r
+          //\r
+          Size = sizeof (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY);    \r
+          Status = ImageContext->ImageRead (\r
+                                   ImageContext->Handle,\r
+                                   DebugDirectoryEntryFileOffset,\r
+                                   &Size,\r
+                                   &DebugEntry\r
+                                   );\r
+          if (RETURN_ERROR (Status)) {\r
+            ImageContext->ImageError = IMAGE_ERROR_IMAGE_READ;\r
+            return Status;\r
+          }\r
+\r
+          if (DebugEntry.Type == EFI_IMAGE_DEBUG_TYPE_CODEVIEW) {\r
+            ImageContext->DebugDirectoryEntryRva = (UINT32) (DebugDirectoryEntryRva + Index);\r
+            if (DebugEntry.RVA == 0 && DebugEntry.FileOffset != 0) {\r
+              ImageContext->ImageSize += DebugEntry.SizeOfData;\r
+            }\r
+\r
+            return RETURN_SUCCESS;\r
+          }\r
+        }\r
+      }\r
+    }\r
+  } else {\r
+    ImageContext->ImageSize         = 0;\r
+    ImageContext->SectionAlignment  = 4096;\r
+    ImageContext->SizeOfHeaders     = sizeof (EFI_TE_IMAGE_HEADER) + (UINTN) TeHdr.BaseOfCode - (UINTN) TeHdr.StrippedSize;\r
+\r
+    DebugDirectoryEntry             = &TeHdr.DataDirectory[1];\r
+    DebugDirectoryEntryRva          = DebugDirectoryEntry->VirtualAddress;\r
+    SectionHeaderOffset             = (UINTN) (sizeof (EFI_TE_IMAGE_HEADER));\r
+\r
+    DebugDirectoryEntryFileOffset   = 0;\r
+\r
+    for (Index = 0; Index < TeHdr.NumberOfSections;) {\r
+      //\r
+      // Read section header from file\r
+      //\r
+      Size = sizeof (EFI_IMAGE_SECTION_HEADER);\r
+      Status = ImageContext->ImageRead (\r
+                               ImageContext->Handle,\r
+                               SectionHeaderOffset,\r
+                               &Size,\r
+                               &SectionHeader\r
+                               );\r
+      if (RETURN_ERROR (Status)) {\r
+        ImageContext->ImageError = IMAGE_ERROR_IMAGE_READ;\r
+        return Status;\r
+      }\r
+\r
+      if (DebugDirectoryEntryRva >= SectionHeader.VirtualAddress &&\r
+          DebugDirectoryEntryRva < SectionHeader.VirtualAddress + SectionHeader.Misc.VirtualSize) {\r
+        DebugDirectoryEntryFileOffset = DebugDirectoryEntryRva -\r
+          SectionHeader.VirtualAddress +\r
+          SectionHeader.PointerToRawData +\r
+          sizeof (EFI_TE_IMAGE_HEADER) -\r
+          TeHdr.StrippedSize;\r
+\r
+        //\r
+        // File offset of the debug directory was found, if this is not the last\r
+        // section, then skip to the last section for calculating the image size.\r
+        //\r
+        if (Index < (UINTN) TeHdr.NumberOfSections - 1) {\r
+          SectionHeaderOffset += (TeHdr.NumberOfSections - 1 - Index) * sizeof (EFI_IMAGE_SECTION_HEADER);\r
+          Index = TeHdr.NumberOfSections - 1;\r
+          continue;\r
+        }\r
+      }\r
+\r
+      //\r
+      // In Te image header there is not a field to describe the ImageSize.\r
+      // Actually, the ImageSize equals the RVA plus the VirtualSize of \r
+      // the last section mapped into memory (Must be rounded up to \r
+      // a mulitple of Section Alignment). Per the PE/COFF specification, the\r
+      // section headers in the Section Table must appear in order of the RVA\r
+      // values for the corresponding sections. So the ImageSize can be determined\r
+      // by the RVA and the VirtualSize of the last section header in the\r
+      // Section Table.\r
+      //\r
+      if ((++Index) == (UINTN) TeHdr.NumberOfSections) {\r
+        ImageContext->ImageSize = (SectionHeader.VirtualAddress + SectionHeader.Misc.VirtualSize +\r
+                                   ImageContext->SectionAlignment - 1) & ~(ImageContext->SectionAlignment - 1);\r
+      }\r
+\r
+      SectionHeaderOffset += sizeof (EFI_IMAGE_SECTION_HEADER);\r
+    }\r
+\r
+    if (DebugDirectoryEntryFileOffset != 0) {\r
+      for (Index = 0; Index < DebugDirectoryEntry->Size; Index += sizeof (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY)) {\r
+        //\r
+        // Read next debug directory entry\r
+        //\r
+        Size = sizeof (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY);\r
+        Status = ImageContext->ImageRead (\r
+                                 ImageContext->Handle,\r
+                                 DebugDirectoryEntryFileOffset,\r
+                                 &Size,\r
+                                 &DebugEntry\r
+                                 );\r
+        if (RETURN_ERROR (Status)) {\r
+          ImageContext->ImageError = IMAGE_ERROR_IMAGE_READ;\r
+          return Status;\r
+        }\r
+\r
+        if (DebugEntry.Type == EFI_IMAGE_DEBUG_TYPE_CODEVIEW) {\r
+          ImageContext->DebugDirectoryEntryRva = (UINT32) (DebugDirectoryEntryRva + Index);\r
+          return RETURN_SUCCESS;\r
+        }\r
+      }\r
+    }\r
+  }\r
+\r
+  return RETURN_SUCCESS;\r
+}\r
+\r
+STATIC\r
+VOID *\r
+PeCoffLoaderImageAddress (\r
+  IN OUT PE_COFF_LOADER_IMAGE_CONTEXT          *ImageContext,\r
+  IN     UINTN                                 Address\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Converts an image address to the loaded address\r
+\r
+Arguments:\r
+\r
+  ImageContext  - The context of the image being loaded\r
+\r
+  Address       - The address to be converted to the loaded address\r
+\r
+Returns:\r
+\r
+  NULL if the address can not be converted, otherwise, the converted address\r
+\r
+--*/\r
+{\r
+  if (Address >= ImageContext->ImageSize) {\r
+    ImageContext->ImageError = IMAGE_ERROR_INVALID_IMAGE_ADDRESS;\r
+    return NULL;\r
+  }\r
+\r
+  return (CHAR8 *) ((UINTN) ImageContext->ImageAddress + Address);\r
+}\r
+\r
+RETURN_STATUS\r
+EFIAPI\r
+PeCoffLoaderRelocateImage (\r
+  IN OUT PE_COFF_LOADER_IMAGE_CONTEXT  *ImageContext\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Relocates a PE/COFF image in memory\r
+\r
+Arguments:\r
+\r
+  This         - Calling context\r
+\r
+  ImageContext - Contains information on the loaded image to relocate\r
+\r
+Returns:\r
+\r
+  RETURN_SUCCESS      if the PE/COFF image was relocated\r
+  RETURN_LOAD_ERROR   if the image is not a valid PE/COFF image\r
+  RETURN_UNSUPPORTED  not support\r
+\r
+--*/\r
+{\r
+  RETURN_STATUS             Status;\r
+  EFI_IMAGE_NT_HEADERS      *PeHdr;\r
+  EFI_TE_IMAGE_HEADER       *TeHdr;\r
+  EFI_IMAGE_DATA_DIRECTORY  *RelocDir;\r
+  UINT64                     Adjust;\r
+  EFI_IMAGE_BASE_RELOCATION *RelocBase;\r
+  EFI_IMAGE_BASE_RELOCATION *RelocBaseEnd;\r
+  UINT16                    *Reloc;\r
+  UINT16                    *RelocEnd;\r
+  CHAR8                     *Fixup;\r
+  CHAR8                     *FixupBase;\r
+  UINT16                    *F16;\r
+  UINT32                    *F32;\r
+  CHAR8                     *FixupData;\r
+  PHYSICAL_ADDRESS          BaseAddress;\r
+  UINT16                    MachineType;\r
+\r
+  PeHdr = NULL;\r
+  TeHdr = NULL;\r
+  //\r
+  // Assume success\r
+  //\r
+  ImageContext->ImageError = IMAGE_ERROR_SUCCESS;\r
+\r
+  //\r
+  // If there are no relocation entries, then we are done\r
+  //\r
+  if (ImageContext->RelocationsStripped) {\r
+    return RETURN_SUCCESS;\r
+  }\r
+\r
+  //\r
+  // If the destination address is not 0, use that rather than the\r
+  // image address as the relocation target.\r
+  //\r
+  if (ImageContext->DestinationAddress) {\r
+    BaseAddress = ImageContext->DestinationAddress;\r
+  } else {\r
+    BaseAddress = ImageContext->ImageAddress;\r
+  }\r
+\r
+  if (!(ImageContext->IsTeImage)) {\r
+    PeHdr = (EFI_IMAGE_NT_HEADERS *)((UINTN)ImageContext->ImageAddress + \r
+                                            ImageContext->PeCoffHeaderOffset);\r
+    Adjust = (UINT64) BaseAddress - PeHdr->OptionalHeader.ImageBase;\r
+    PeHdr->OptionalHeader.ImageBase = (UINTN) BaseAddress;\r
+    MachineType = PeHdr->FileHeader.Machine;\r
+    //\r
+    // Find the relocation block\r
+    //\r
+    // Per the PE/COFF spec, you can't assume that a given data directory\r
+    // is present in the image. You have to check the NumberOfRvaAndSizes in\r
+    // the optional header to verify a desired directory entry is there.\r
+    //\r
+    if (PeHdr->OptionalHeader.NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC) {\r
+      RelocDir  = &PeHdr->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC];\r
+      RelocBase = PeCoffLoaderImageAddress (ImageContext, RelocDir->VirtualAddress);\r
+      RelocBaseEnd = PeCoffLoaderImageAddress (\r
+                      ImageContext,\r
+                      RelocDir->VirtualAddress + RelocDir->Size - 1\r
+                      );\r
+    } else {\r
+      //\r
+      // Set base and end to bypass processing below.\r
+      //\r
+      RelocBase = RelocBaseEnd = 0;\r
+    }\r
+  } else {\r
+    TeHdr             = (EFI_TE_IMAGE_HEADER *) (UINTN) (ImageContext->ImageAddress);\r
+    Adjust            = (UINT64) (BaseAddress - TeHdr->ImageBase);\r
+    TeHdr->ImageBase  = (UINT64) (BaseAddress);\r
+    MachineType = TeHdr->Machine;\r
+    \r
+    //\r
+    // Find the relocation block\r
+    //\r
+    RelocDir = &TeHdr->DataDirectory[0];\r
+    RelocBase = (EFI_IMAGE_BASE_RELOCATION *)(UINTN)(\r
+                                    ImageContext->ImageAddress + \r
+                                    RelocDir->VirtualAddress +\r
+                                    sizeof(EFI_TE_IMAGE_HEADER) - \r
+                                    TeHdr->StrippedSize\r
+                                    );\r
+    RelocBaseEnd = (EFI_IMAGE_BASE_RELOCATION *) ((UINTN) RelocBase + (UINTN) RelocDir->Size - 1);\r
+  }\r
+  \r
+  //\r
+  // Run the relocation information and apply the fixups\r
+  //\r
+  FixupData = ImageContext->FixupData;\r
+  while (RelocBase < RelocBaseEnd) {\r
+\r
+    Reloc     = (UINT16 *) ((CHAR8 *) RelocBase + sizeof (EFI_IMAGE_BASE_RELOCATION));\r
+    RelocEnd  = (UINT16 *) ((CHAR8 *) RelocBase + RelocBase->SizeOfBlock);\r
+    if (!(ImageContext->IsTeImage)) {\r
+      FixupBase = PeCoffLoaderImageAddress (ImageContext, RelocBase->VirtualAddress);\r
+    } else {\r
+      FixupBase = (CHAR8 *)(UINTN)(ImageContext->ImageAddress +\r
+                    RelocBase->VirtualAddress +\r
+                    sizeof(EFI_TE_IMAGE_HEADER) - \r
+                    TeHdr->StrippedSize\r
+                    );\r
+    }\r
+\r
+    if ((CHAR8 *) RelocEnd < (CHAR8 *) ((UINTN) ImageContext->ImageAddress) ||\r
+        (CHAR8 *) RelocEnd > (CHAR8 *)((UINTN)ImageContext->ImageAddress + \r
+          (UINTN)ImageContext->ImageSize)) {\r
+      ImageContext->ImageError = IMAGE_ERROR_FAILED_RELOCATION;\r
+      return RETURN_LOAD_ERROR;\r
+    }\r
+\r
+    //\r
+    // Run this relocation record\r
+    //\r
+    while (Reloc < RelocEnd) {\r
+\r
+      Fixup = FixupBase + (*Reloc & 0xFFF);\r
+      switch ((*Reloc) >> 12) {\r
+      case EFI_IMAGE_REL_BASED_ABSOLUTE:\r
+        break;\r
+\r
+      case EFI_IMAGE_REL_BASED_HIGH:\r
+        F16   = (UINT16 *) Fixup;\r
+        *F16 = (UINT16) (*F16 + ((UINT16) ((UINT32) Adjust >> 16)));\r
+        if (FixupData != NULL) {\r
+          *(UINT16 *) FixupData = *F16;\r
+          FixupData             = FixupData + sizeof (UINT16);\r
+        }\r
+        break;\r
+\r
+      case EFI_IMAGE_REL_BASED_LOW:\r
+        F16   = (UINT16 *) Fixup;\r
+        *F16  = (UINT16) (*F16 + (UINT16) Adjust);\r
+        if (FixupData != NULL) {\r
+          *(UINT16 *) FixupData = *F16;\r
+          FixupData             = FixupData + sizeof (UINT16);\r
+        }\r
+        break;\r
+\r
+      case EFI_IMAGE_REL_BASED_HIGHLOW:\r
+        F32   = (UINT32 *) Fixup;\r
+        *F32  = *F32 + (UINT32) Adjust;\r
+        if (FixupData != NULL) {\r
+          FixupData             = ALIGN_POINTER (FixupData, sizeof (UINT32));\r
+          *(UINT32 *) FixupData = *F32;\r
+          FixupData             = FixupData + sizeof (UINT32);\r
+        }\r
+        break;\r
+\r
+      case EFI_IMAGE_REL_BASED_HIGHADJ:\r
+        //\r
+        // Return the same EFI_UNSUPPORTED return code as\r
+        // PeCoffLoaderRelocateImageEx() returns if it does not recognize\r
+        // the relocation type.\r
+        //\r
+        ImageContext->ImageError = IMAGE_ERROR_FAILED_RELOCATION;\r
+        return RETURN_UNSUPPORTED;\r
+\r
+      default:\r
+        switch (MachineType) {\r
+        case EFI_IMAGE_MACHINE_IA32:\r
+          Status = PeCoffLoaderRelocateIa32Image (Reloc, Fixup, &FixupData, Adjust);\r
+          break;\r
+        case EFI_IMAGE_MACHINE_X64:\r
+          Status = PeCoffLoaderRelocateX64Image (Reloc, Fixup, &FixupData, Adjust);\r
+          break;\r
+        case EFI_IMAGE_MACHINE_IA64:\r
+          Status = PeCoffLoaderRelocateIpfImage (Reloc, Fixup, &FixupData, Adjust);\r
+          break;\r
+        default:\r
+          Status = RETURN_UNSUPPORTED;\r
+          break;\r
+        }\r
+        if (RETURN_ERROR (Status)) {\r
+          ImageContext->ImageError = IMAGE_ERROR_FAILED_RELOCATION;\r
+          return Status;\r
+        }\r
+      }\r
+\r
+      //\r
+      // Next relocation record\r
+      //\r
+      Reloc += 1;\r
+    }\r
+\r
+    //\r
+    // Next reloc block\r
+    //\r
+    RelocBase = (EFI_IMAGE_BASE_RELOCATION *) RelocEnd;\r
+  }\r
+\r
+  return RETURN_SUCCESS;\r
+}\r
+\r
+RETURN_STATUS\r
+EFIAPI\r
+PeCoffLoaderLoadImage (\r
+  IN OUT PE_COFF_LOADER_IMAGE_CONTEXT  *ImageContext\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Loads a PE/COFF image into memory\r
+\r
+Arguments:\r
+\r
+  This         - Calling context\r
+\r
+  ImageContext - Contains information on image to load into memory\r
+\r
+Returns:\r
+\r
+  RETURN_SUCCESS            if the PE/COFF image was loaded\r
+  RETURN_BUFFER_TOO_SMALL   if the caller did not provide a large enough buffer\r
+  RETURN_LOAD_ERROR         if the image is a runtime driver with no relocations\r
+  RETURN_INVALID_PARAMETER  if the image address is invalid\r
+\r
+--*/\r
+{\r
+  RETURN_STATUS                            Status;\r
+  EFI_IMAGE_NT_HEADERS                  *PeHdr;\r
+  EFI_TE_IMAGE_HEADER                   *TeHdr;\r
+  PE_COFF_LOADER_IMAGE_CONTEXT  CheckContext;\r
+  EFI_IMAGE_SECTION_HEADER              *FirstSection;\r
+  EFI_IMAGE_SECTION_HEADER              *Section;\r
+  UINTN                                 NumberOfSections;\r
+  UINTN                                 Index;\r
+  CHAR8                                 *Base;\r
+  CHAR8                                 *End;\r
+  CHAR8                                 *MaxEnd;\r
+  EFI_IMAGE_DATA_DIRECTORY              *DirectoryEntry;\r
+  EFI_IMAGE_DEBUG_DIRECTORY_ENTRY       *DebugEntry;\r
+  UINTN                                 Size;\r
+  UINT32                                TempDebugEntryRva;\r
+\r
+  PeHdr = NULL;\r
+  TeHdr = NULL;\r
+  //\r
+  // Assume success\r
+  //\r
+  ImageContext->ImageError = IMAGE_ERROR_SUCCESS;\r
+\r
+  //\r
+  // Copy the provided context info into our local version, get what we\r
+  // can from the original image, and then use that to make sure everything\r
+  // is legit.\r
+  //\r
+  CopyMem (&CheckContext, ImageContext, sizeof (PE_COFF_LOADER_IMAGE_CONTEXT));\r
+\r
+  Status = PeCoffLoaderGetImageInfo (&CheckContext);\r
+  if (RETURN_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  //\r
+  // Make sure there is enough allocated space for the image being loaded\r
+  //\r
+  if (ImageContext->ImageSize < CheckContext.ImageSize) {\r
+    ImageContext->ImageError = IMAGE_ERROR_INVALID_IMAGE_SIZE;\r
+    return RETURN_BUFFER_TOO_SMALL;\r
+  }\r
+\r
+  //\r
+  // If there's no relocations, then make sure it's not a runtime driver,\r
+  // and that it's being loaded at the linked address.\r
+  //\r
+  if (CheckContext.RelocationsStripped) {\r
+    //\r
+    // If the image does not contain relocations and it is a runtime driver\r
+    // then return an error.\r
+    //\r
+    if (CheckContext.ImageType == EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER) {\r
+      ImageContext->ImageError = IMAGE_ERROR_INVALID_SUBSYSTEM;\r
+      return RETURN_LOAD_ERROR;\r
+    }\r
+    //\r
+    // If the image does not contain relocations, and the requested load address\r
+    // is not the linked address, then return an error.\r
+    //\r
+    if (CheckContext.ImageAddress != ImageContext->ImageAddress) {\r
+      ImageContext->ImageError = IMAGE_ERROR_INVALID_IMAGE_ADDRESS;\r
+      return RETURN_INVALID_PARAMETER;\r
+    }\r
+  }\r
+  //\r
+  // Make sure the allocated space has the proper section alignment\r
+  //\r
+  if (!(ImageContext->IsTeImage)) {\r
+    if ((ImageContext->ImageAddress & (CheckContext.SectionAlignment - 1)) != 0) {\r
+      ImageContext->ImageError = IMAGE_ERROR_INVALID_SECTION_ALIGNMENT;\r
+      return RETURN_INVALID_PARAMETER;\r
+    }\r
+  }\r
+  //\r
+  // Read the entire PE/COFF or TE header into memory\r
+  //\r
+  if (!(ImageContext->IsTeImage)) {\r
+    Status = ImageContext->ImageRead (\r
+                            ImageContext->Handle,\r
+                            0,\r
+                            &ImageContext->SizeOfHeaders,\r
+                            (VOID *) (UINTN) ImageContext->ImageAddress\r
+                            );\r
+\r
+    PeHdr = (EFI_IMAGE_NT_HEADERS *)\r
+      ((UINTN)ImageContext->ImageAddress + ImageContext->PeCoffHeaderOffset);\r
+\r
+    FirstSection = (EFI_IMAGE_SECTION_HEADER *) (\r
+                      (UINTN)ImageContext->ImageAddress +\r
+                      ImageContext->PeCoffHeaderOffset +\r
+                      sizeof(UINT32) + \r
+                      sizeof(EFI_IMAGE_FILE_HEADER) + \r
+                      PeHdr->FileHeader.SizeOfOptionalHeader\r
+      );\r
+    NumberOfSections = (UINTN) (PeHdr->FileHeader.NumberOfSections);\r
+  } else {\r
+    Status = ImageContext->ImageRead (\r
+                            ImageContext->Handle,\r
+                            0,\r
+                            &ImageContext->SizeOfHeaders,\r
+                            (void *) (UINTN) ImageContext->ImageAddress\r
+                            );\r
+\r
+    TeHdr             = (EFI_TE_IMAGE_HEADER *) (UINTN) (ImageContext->ImageAddress);\r
+\r
+    FirstSection = (EFI_IMAGE_SECTION_HEADER *) (\r
+          (UINTN)ImageContext->ImageAddress +\r
+          sizeof(EFI_TE_IMAGE_HEADER)\r
+          );\r
+    NumberOfSections  = (UINTN) (TeHdr->NumberOfSections);\r
+\r
+  }\r
+\r
+  if (RETURN_ERROR (Status)) {\r
+    ImageContext->ImageError = IMAGE_ERROR_IMAGE_READ;\r
+    return RETURN_LOAD_ERROR;\r
+  }\r
+\r
+  //\r
+  // Load each section of the image\r
+  //\r
+  Section = FirstSection;\r
+  for (Index = 0, MaxEnd = NULL; Index < NumberOfSections; Index++) {\r
+\r
+    //\r
+    // Compute sections address\r
+    //\r
+    Base = PeCoffLoaderImageAddress (ImageContext, Section->VirtualAddress);\r
+    End = PeCoffLoaderImageAddress (\r
+            ImageContext,\r
+            Section->VirtualAddress + Section->Misc.VirtualSize - 1\r
+            );\r
+    if (ImageContext->IsTeImage) {\r
+      Base  = (CHAR8 *) ((UINTN) Base + sizeof (EFI_TE_IMAGE_HEADER) - (UINTN) TeHdr->StrippedSize);\r
+      End   = (CHAR8 *) ((UINTN) End + sizeof (EFI_TE_IMAGE_HEADER) - (UINTN) TeHdr->StrippedSize);\r
+    }\r
+\r
+    if (End > MaxEnd) {\r
+      MaxEnd = End;\r
+    }\r
+    //\r
+    // If the base start or end address resolved to 0, then fail.\r
+    //\r
+    if ((Base == NULL) || (End == NULL)) {\r
+      ImageContext->ImageError = IMAGE_ERROR_SECTION_NOT_LOADED;\r
+      return RETURN_LOAD_ERROR;\r
+    }\r
+\r
+    //\r
+    // Read the section\r
+    //\r
+    Size = (UINTN) Section->Misc.VirtualSize;\r
+    if ((Size == 0) || (Size > Section->SizeOfRawData)) {\r
+      Size = (UINTN) Section->SizeOfRawData;\r
+    }\r
+\r
+    if (Section->SizeOfRawData) {\r
+      if (!(ImageContext->IsTeImage)) {\r
+        Status = ImageContext->ImageRead (\r
+                                ImageContext->Handle,\r
+                                Section->PointerToRawData,\r
+                                &Size,\r
+                                Base\r
+                                );\r
+      } else {\r
+        Status = ImageContext->ImageRead (\r
+                                ImageContext->Handle,\r
+                                Section->PointerToRawData + sizeof (EFI_TE_IMAGE_HEADER) - (UINTN) TeHdr->StrippedSize,\r
+                                &Size,\r
+                                Base\r
+                                );\r
+      }\r
+\r
+      if (RETURN_ERROR (Status)) {\r
+        ImageContext->ImageError = IMAGE_ERROR_IMAGE_READ;\r
+        return Status;\r
+      }\r
+    }\r
+\r
+    //\r
+    // If raw size is less then virt size, zero fill the remaining\r
+    //\r
+\r
+    if (Size < Section->Misc.VirtualSize) {\r
+      ZeroMem (Base + Size, Section->Misc.VirtualSize - Size);\r
+    }\r
+\r
+    //\r
+    // Next Section\r
+    //\r
+    Section += 1;\r
+  }\r
+\r
+  //\r
+  // Get image's entry point\r
+  //\r
+  if (!(ImageContext->IsTeImage)) {\r
+    ImageContext->EntryPoint = (PHYSICAL_ADDRESS) (UINTN) PeCoffLoaderImageAddress (\r
+                                                                ImageContext,\r
+                                                                PeHdr->OptionalHeader.AddressOfEntryPoint\r
+                                                                );\r
+  } else {\r
+    ImageContext->EntryPoint =  (PHYSICAL_ADDRESS) (\r
+                       (UINTN)ImageContext->ImageAddress +\r
+                       (UINTN)TeHdr->AddressOfEntryPoint +\r
+                       (UINTN)sizeof(EFI_TE_IMAGE_HEADER) -\r
+          (UINTN) TeHdr->StrippedSize\r
+      );\r
+  }\r
+\r
+  //\r
+  // Determine the size of the fixup data\r
+  //\r
+  // Per the PE/COFF spec, you can't assume that a given data directory\r
+  // is present in the image. You have to check the NumberOfRvaAndSizes in\r
+  // the optional header to verify a desired directory entry is there.\r
+  //\r
+  if (!(ImageContext->IsTeImage)) {\r
+    if (PeHdr->OptionalHeader.NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC) {\r
+      DirectoryEntry = (EFI_IMAGE_DATA_DIRECTORY *)\r
+        &PeHdr->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC];\r
+      ImageContext->FixupDataSize = DirectoryEntry->Size / sizeof (UINT16) * sizeof (UINTN);\r
+    } else {\r
+      ImageContext->FixupDataSize = 0;\r
+    }\r
+  } else {\r
+    DirectoryEntry              = &TeHdr->DataDirectory[0];\r
+    ImageContext->FixupDataSize = DirectoryEntry->Size / sizeof (UINT16) * sizeof (UINTN);\r
+  }\r
+  //\r
+  // Consumer must allocate a buffer for the relocation fixup log.\r
+  // Only used for runtime drivers.\r
+  //\r
+  ImageContext->FixupData = NULL;\r
+\r
+  //\r
+  // Load the Codeview info if present\r
+  //\r
+  if (ImageContext->DebugDirectoryEntryRva != 0) {\r
+    if (!(ImageContext->IsTeImage)) {\r
+      DebugEntry = PeCoffLoaderImageAddress (\r
+                    ImageContext,\r
+                    ImageContext->DebugDirectoryEntryRva\r
+                    );\r
+    } else {\r
+      DebugEntry = (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY *)(UINTN)(\r
+                                               ImageContext->ImageAddress +\r
+                                               ImageContext->DebugDirectoryEntryRva +\r
+                                               sizeof(EFI_TE_IMAGE_HEADER) -\r
+                                               TeHdr->StrippedSize\r
+                                               );\r
+    }\r
+\r
+    if (DebugEntry != NULL) {\r
+      TempDebugEntryRva = DebugEntry->RVA;\r
+      if (DebugEntry->RVA == 0 && DebugEntry->FileOffset != 0) {\r
+        Section--;\r
+        if ((UINTN) Section->SizeOfRawData < Section->Misc.VirtualSize) {\r
+          TempDebugEntryRva = Section->VirtualAddress + Section->Misc.VirtualSize;\r
+        } else {\r
+          TempDebugEntryRva = Section->VirtualAddress + Section->SizeOfRawData;\r
+        }\r
+      }\r
+\r
+      if (TempDebugEntryRva != 0) {\r
+        if (!(ImageContext->IsTeImage)) {\r
+          ImageContext->CodeView = PeCoffLoaderImageAddress (ImageContext, TempDebugEntryRva);\r
+        } else {\r
+          ImageContext->CodeView = (VOID *)(\r
+                      (UINTN)ImageContext->ImageAddress +\r
+                      (UINTN)TempDebugEntryRva +\r
+                      (UINTN)sizeof(EFI_TE_IMAGE_HEADER) -\r
+                (UINTN) TeHdr->StrippedSize\r
+            );\r
+        }\r
+\r
+        if (ImageContext->CodeView == NULL) {\r
+          ImageContext->ImageError = IMAGE_ERROR_IMAGE_READ;\r
+          return RETURN_LOAD_ERROR;\r
+        }\r
+\r
+        if (DebugEntry->RVA == 0) {\r
+          Size = DebugEntry->SizeOfData;\r
+          if (!(ImageContext->IsTeImage)) {\r
+            Status = ImageContext->ImageRead (\r
+                                    ImageContext->Handle,\r
+                                    DebugEntry->FileOffset,\r
+                                    &Size,\r
+                                    ImageContext->CodeView\r
+                                    );\r
+          } else {\r
+            Status = ImageContext->ImageRead (\r
+                                    ImageContext->Handle,\r
+                                    DebugEntry->FileOffset + sizeof (EFI_TE_IMAGE_HEADER) - TeHdr->StrippedSize,\r
+                                    &Size,\r
+                                    ImageContext->CodeView\r
+                                    );\r
+            //\r
+            // Should we apply fix up to this field according to the size difference between PE and TE?\r
+            // Because now we maintain TE header fields unfixed, this field will also remain as they are\r
+            // in original PE image.\r
+            //\r
+          }\r
+\r
+          if (RETURN_ERROR (Status)) {\r
+            ImageContext->ImageError = IMAGE_ERROR_IMAGE_READ;\r
+            return RETURN_LOAD_ERROR;\r
+          }\r
+\r
+          DebugEntry->RVA = TempDebugEntryRva;\r
+        }\r
+\r
+        switch (*(UINT32 *) ImageContext->CodeView) {\r
+        case CODEVIEW_SIGNATURE_NB10:\r
+          ImageContext->PdbPointer = (CHAR8 *) ImageContext->CodeView + sizeof (EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY);\r
+          break;\r
+\r
+        case CODEVIEW_SIGNATURE_RSDS:\r
+          ImageContext->PdbPointer = (CHAR8 *) ImageContext->CodeView + sizeof (EFI_IMAGE_DEBUG_CODEVIEW_RSDS_ENTRY);\r
+          break;\r
+\r
+        default:\r
+          break;\r
+        }\r
+      }\r
+    }\r
+  }\r
+\r
+  return Status;\r
+}\r
diff --git a/Source/C/PeCoffLoader/Makefile b/Source/C/PeCoffLoader/Makefile
new file mode 100644 (file)
index 0000000..1679cab
--- /dev/null
@@ -0,0 +1,8 @@
+!INCLUDE ..\MSmakefile.common\r
+\r
+LIBNAME = PeCoffLoader\r
+\r
+OBJECTS = BasePeCoff.obj PeCoffLoaderEx.obj\r
+\r
+!INCLUDE ..\MSmakefile.lib\r
+\r
diff --git a/Source/C/PeCoffLoader/PeCoffLoaderEx.c b/Source/C/PeCoffLoader/PeCoffLoaderEx.c
new file mode 100644 (file)
index 0000000..99e7c93
--- /dev/null
@@ -0,0 +1,317 @@
+/*++\r
+\r
+Copyright (c) 2004, Intel Corporation                                                         \r
+All rights reserved. This program and the accompanying materials                          \r
+are licensed and made available under the terms and conditions of the BSD License         \r
+which accompanies this distribution.  The full text of the license may be found at        \r
+http://opensource.org/licenses/bsd-license.php                                            \r
+                                                                                          \r
+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
+    PeCoffLoaderEx.c\r
+\r
+Abstract:\r
+\r
+    IA32, X64 and IPF Specific relocation fixups\r
+\r
+Revision History\r
+\r
+--*/\r
+\r
+#include <Common/UefiBaseTypes.h>\r
+#include <Common/EfiImage.h>\r
+#include <Library/PeCoffLib.h>\r
+\r
+#define EXT_IMM64(Value, Address, Size, InstPos, ValPos)  \\r
+    Value |= (((UINT64)((*(Address) >> InstPos) & (((UINT64)1 << Size) - 1))) << ValPos)\r
+\r
+#define INS_IMM64(Value, Address, Size, InstPos, ValPos)  \\r
+    *(UINT32*)Address = (*(UINT32*)Address & ~(((1 << Size) - 1) << InstPos)) | \\r
+          ((UINT32)((((UINT64)Value >> ValPos) & (((UINT64)1 << Size) - 1))) << InstPos)\r
+\r
+#define IMM64_IMM7B_INST_WORD_X         3  \r
+#define IMM64_IMM7B_SIZE_X              7  \r
+#define IMM64_IMM7B_INST_WORD_POS_X     4  \r
+#define IMM64_IMM7B_VAL_POS_X           0  \r
+\r
+#define IMM64_IMM9D_INST_WORD_X         3  \r
+#define IMM64_IMM9D_SIZE_X              9  \r
+#define IMM64_IMM9D_INST_WORD_POS_X     18  \r
+#define IMM64_IMM9D_VAL_POS_X           7  \r
+\r
+#define IMM64_IMM5C_INST_WORD_X         3  \r
+#define IMM64_IMM5C_SIZE_X              5  \r
+#define IMM64_IMM5C_INST_WORD_POS_X     13  \r
+#define IMM64_IMM5C_VAL_POS_X           16  \r
+\r
+#define IMM64_IC_INST_WORD_X            3  \r
+#define IMM64_IC_SIZE_X                 1  \r
+#define IMM64_IC_INST_WORD_POS_X        12  \r
+#define IMM64_IC_VAL_POS_X              21  \r
+\r
+#define IMM64_IMM41a_INST_WORD_X        1  \r
+#define IMM64_IMM41a_SIZE_X             10  \r
+#define IMM64_IMM41a_INST_WORD_POS_X    14  \r
+#define IMM64_IMM41a_VAL_POS_X          22  \r
+\r
+#define IMM64_IMM41b_INST_WORD_X        1  \r
+#define IMM64_IMM41b_SIZE_X             8  \r
+#define IMM64_IMM41b_INST_WORD_POS_X    24  \r
+#define IMM64_IMM41b_VAL_POS_X          32  \r
+\r
+#define IMM64_IMM41c_INST_WORD_X        2  \r
+#define IMM64_IMM41c_SIZE_X             23  \r
+#define IMM64_IMM41c_INST_WORD_POS_X    0  \r
+#define IMM64_IMM41c_VAL_POS_X          40  \r
+\r
+#define IMM64_SIGN_INST_WORD_X          3  \r
+#define IMM64_SIGN_SIZE_X               1  \r
+#define IMM64_SIGN_INST_WORD_POS_X      27  \r
+#define IMM64_SIGN_VAL_POS_X            63  \r
+\r
+RETURN_STATUS\r
+PeCoffLoaderRelocateIa32Image (\r
+  IN UINT16      *Reloc,\r
+  IN OUT CHAR8   *Fixup,\r
+  IN OUT CHAR8   **FixupData,\r
+  IN UINT64      Adjust\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Performs an IA-32 specific relocation fixup\r
+\r
+Arguments:\r
+\r
+  Reloc      - Pointer to the relocation record\r
+\r
+  Fixup      - Pointer to the address to fix up\r
+\r
+  FixupData  - Pointer to a buffer to log the fixups\r
+\r
+  Adjust     - The offset to adjust the fixup\r
+\r
+Returns:\r
+\r
+  EFI_UNSUPPORTED   - Unsupported now\r
+\r
+--*/\r
+{\r
+  return RETURN_UNSUPPORTED;\r
+}\r
+\r
+RETURN_STATUS\r
+PeCoffLoaderRelocateIpfImage (\r
+  IN UINT16      *Reloc,\r
+  IN OUT CHAR8   *Fixup, \r
+  IN OUT CHAR8   **FixupData,\r
+  IN UINT64      Adjust\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Performs an Itanium-based specific relocation fixup\r
+\r
+Arguments:\r
+\r
+  Reloc      - Pointer to the relocation record\r
+\r
+  Fixup      - Pointer to the address to fix up\r
+\r
+  FixupData  - Pointer to a buffer to log the fixups\r
+\r
+  Adjust     - The offset to adjust the fixup\r
+\r
+Returns:\r
+\r
+  Status code\r
+\r
+--*/\r
+{\r
+  UINT64      *F64;\r
+  UINT64      FixupVal;\r
+\r
+  switch ((*Reloc) >> 12) {\r
+\r
+    case EFI_IMAGE_REL_BASED_DIR64:\r
+      F64 = (UINT64 *) Fixup;\r
+      *F64 = *F64 + (UINT64) Adjust;\r
+      if (*FixupData != NULL) {\r
+        *FixupData = ALIGN_POINTER(*FixupData, sizeof(UINT64));\r
+        *(UINT64 *)(*FixupData) = *F64;\r
+        *FixupData = *FixupData + sizeof(UINT64);\r
+      }\r
+      break;\r
+\r
+    case EFI_IMAGE_REL_BASED_IA64_IMM64:\r
+\r
+      //\r
+      // Align it to bundle address before fixing up the\r
+      // 64-bit immediate value of the movl instruction.\r
+      //\r
+\r
+      Fixup = (CHAR8 *)((UINTN) Fixup & (UINTN) ~(15));\r
+      FixupVal = (UINT64)0;\r
+                       \r
+      // \r
+      // Extract the lower 32 bits of IMM64 from bundle\r
+      //\r
+      EXT_IMM64(FixupVal,\r
+                (UINT32 *)Fixup + IMM64_IMM7B_INST_WORD_X,\r
+                IMM64_IMM7B_SIZE_X,\r
+                IMM64_IMM7B_INST_WORD_POS_X,\r
+                IMM64_IMM7B_VAL_POS_X\r
+                );\r
+\r
+      EXT_IMM64(FixupVal,\r
+                (UINT32 *)Fixup + IMM64_IMM9D_INST_WORD_X,\r
+                IMM64_IMM9D_SIZE_X,\r
+                IMM64_IMM9D_INST_WORD_POS_X,\r
+                IMM64_IMM9D_VAL_POS_X\r
+                );\r
+\r
+      EXT_IMM64(FixupVal,\r
+                (UINT32 *)Fixup + IMM64_IMM5C_INST_WORD_X,\r
+                IMM64_IMM5C_SIZE_X,\r
+                IMM64_IMM5C_INST_WORD_POS_X,\r
+                IMM64_IMM5C_VAL_POS_X\r
+                );\r
+\r
+      EXT_IMM64(FixupVal,\r
+                (UINT32 *)Fixup + IMM64_IC_INST_WORD_X,\r
+                IMM64_IC_SIZE_X,\r
+                IMM64_IC_INST_WORD_POS_X,\r
+                IMM64_IC_VAL_POS_X\r
+                );\r
+\r
+      EXT_IMM64(FixupVal,\r
+                (UINT32 *)Fixup + IMM64_IMM41a_INST_WORD_X,\r
+                IMM64_IMM41a_SIZE_X,\r
+                IMM64_IMM41a_INST_WORD_POS_X,\r
+                IMM64_IMM41a_VAL_POS_X\r
+                );\r
+                       \r
+      // \r
+      // Update 64-bit address\r
+      //\r
+      FixupVal += Adjust;\r
+\r
+      // \r
+      // Insert IMM64 into bundle\r
+      //\r
+      INS_IMM64(FixupVal,\r
+                ((UINT32 *)Fixup + IMM64_IMM7B_INST_WORD_X),\r
+                IMM64_IMM7B_SIZE_X,\r
+                IMM64_IMM7B_INST_WORD_POS_X,\r
+                IMM64_IMM7B_VAL_POS_X\r
+                );\r
+\r
+      INS_IMM64(FixupVal,\r
+                ((UINT32 *)Fixup + IMM64_IMM9D_INST_WORD_X),\r
+                IMM64_IMM9D_SIZE_X,\r
+                IMM64_IMM9D_INST_WORD_POS_X,\r
+                IMM64_IMM9D_VAL_POS_X\r
+                );\r
+\r
+      INS_IMM64(FixupVal,\r
+                ((UINT32 *)Fixup + IMM64_IMM5C_INST_WORD_X),\r
+                IMM64_IMM5C_SIZE_X,\r
+                IMM64_IMM5C_INST_WORD_POS_X,\r
+                IMM64_IMM5C_VAL_POS_X\r
+                );\r
+\r
+      INS_IMM64(FixupVal,\r
+                ((UINT32 *)Fixup + IMM64_IC_INST_WORD_X),\r
+                IMM64_IC_SIZE_X,\r
+                IMM64_IC_INST_WORD_POS_X,\r
+                IMM64_IC_VAL_POS_X\r
+                );\r
+\r
+      INS_IMM64(FixupVal,\r
+                ((UINT32 *)Fixup + IMM64_IMM41a_INST_WORD_X),\r
+                IMM64_IMM41a_SIZE_X,\r
+                IMM64_IMM41a_INST_WORD_POS_X,\r
+                IMM64_IMM41a_VAL_POS_X\r
+                );\r
+\r
+      INS_IMM64(FixupVal,\r
+                ((UINT32 *)Fixup + IMM64_IMM41b_INST_WORD_X),\r
+                IMM64_IMM41b_SIZE_X,\r
+                IMM64_IMM41b_INST_WORD_POS_X,\r
+                IMM64_IMM41b_VAL_POS_X\r
+                );\r
+\r
+      INS_IMM64(FixupVal,\r
+                ((UINT32 *)Fixup + IMM64_IMM41c_INST_WORD_X),\r
+                IMM64_IMM41c_SIZE_X,\r
+                IMM64_IMM41c_INST_WORD_POS_X,\r
+                IMM64_IMM41c_VAL_POS_X\r
+                );\r
+\r
+      INS_IMM64(FixupVal,\r
+                ((UINT32 *)Fixup + IMM64_SIGN_INST_WORD_X),\r
+                IMM64_SIGN_SIZE_X,\r
+                IMM64_SIGN_INST_WORD_POS_X,\r
+                IMM64_SIGN_VAL_POS_X\r
+                );\r
+\r
+      F64 = (UINT64 *) Fixup;\r
+      if (*FixupData != NULL) {\r
+        *FixupData = ALIGN_POINTER(*FixupData, sizeof(UINT64));\r
+        *(UINT64 *)(*FixupData) = *F64;\r
+        *FixupData = *FixupData + sizeof(UINT64);\r
+      }\r
+      break;\r
+\r
+    default:\r
+      return RETURN_UNSUPPORTED;\r
+  }\r
+\r
+  return RETURN_SUCCESS;\r
+}\r
+\r
+RETURN_STATUS\r
+PeCoffLoaderRelocateX64Image (\r
+  IN     UINT16       *Reloc,\r
+  IN OUT CHAR8        *Fixup, \r
+  IN OUT CHAR8        **FixupData,\r
+  IN     UINT64       Adjust\r
+  )\r
+/**\r
+  Performs an x64 specific relocation fixup\r
+\r
+  @param Reloc        Pointer to the relocation record\r
+  @param Fixup        Pointer to the address to fix up\r
+  @param FixupData    Pointer to a buffer to log the fixups\r
+  @param Adjust       The offset to adjust the fixup\r
+  \r
+  @retval RETURN_SUCCESS      Success to perform relocation\r
+  @retval RETURN_UNSUPPORTED  Unsupported.\r
+**/\r
+{\r
+  UINT64      *F64;\r
+\r
+  switch ((*Reloc) >> 12) {\r
+\r
+    case EFI_IMAGE_REL_BASED_DIR64:\r
+      F64 = (UINT64 *) Fixup;\r
+      *F64 = *F64 + (UINT64) Adjust;\r
+      if (*FixupData != NULL) {\r
+        *FixupData = ALIGN_POINTER(*FixupData, sizeof(UINT64));\r
+        *(UINT64 *)(*FixupData) = *F64;\r
+        *FixupData = *FixupData + sizeof(UINT64);\r
+      }\r
+      break;\r
+\r
+    default:\r
+      return RETURN_UNSUPPORTED;\r
+  }\r
+\r
+  return RETURN_SUCCESS;\r
+}\r
+\r