]> git.proxmox.com Git - mirror_edk2.git/blobdiff - EdkCompatibilityPkg/Sample/Tools/Source/GenFvImage/GenFvImageLib.c
Add in the 1st version of ECP.
[mirror_edk2.git] / EdkCompatibilityPkg / Sample / Tools / Source / GenFvImage / GenFvImageLib.c
diff --git a/EdkCompatibilityPkg/Sample/Tools/Source/GenFvImage/GenFvImageLib.c b/EdkCompatibilityPkg/Sample/Tools/Source/GenFvImage/GenFvImageLib.c
new file mode 100644 (file)
index 0000000..3c59184
--- /dev/null
@@ -0,0 +1,3054 @@
+/*++\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
+  GenFvImageLib.c\r
+\r
+Abstract:\r
+\r
+  This file contains functions required to generate a Firmware Volume.\r
+\r
+--*/\r
+\r
+//\r
+// Include files\r
+//\r
+#include "GenFvImageLib.h"\r
+#include "GenFvImageLibInternal.h"\r
+#include <string.h>\r
+#include EFI_GUID_DEFINITION (PeiPeCoffLoader)\r
+#include "EfiFirmwareFileSystem.h"\r
+#include "EfiWorkingBlockHeader.h"\r
+#include "EfiVariable.h"\r
+#include <io.h>\r
+#include <assert.h>\r
+#include "CommonLib.h"\r
+#include "FvLib.h"\r
+#include "EfiImage.h"\r
+#include "crc32.h"\r
+#include "EfiUtilityMsgs.h"\r
+#include EFI_GUID_DEFINITION (FirmwareFileSystem)\r
+#include EFI_GUID_DEFINITION (FirmwareFileSystem2)\r
+\r
+//\r
+// Define the PE/COFF loader\r
+//\r
+extern EFI_PEI_PE_COFF_LOADER_PROTOCOL  mPeCoffLoader;\r
+\r
+//\r
+// Local function prototypes\r
+//\r
+EFI_STATUS\r
+GetPe32Info (\r
+  IN UINT8                  *Pe32,\r
+  OUT UINT32                *EntryPoint,\r
+  OUT UINT32                *BaseOfCode,\r
+  OUT UINT16                *MachineType\r
+  );\r
+\r
+//\r
+// Local function implementations.\r
+//\r
+#if (PI_SPECIFICATION_VERSION < 0x00010000)\r
+EFI_GUID  FfsGuid = EFI_FIRMWARE_FILE_SYSTEM_GUID;\r
+#else\r
+EFI_GUID  FfsGuid = EFI_FIRMWARE_FILE_SYSTEM2_GUID;\r
+#endif\r
+\r
+EFI_GUID  DefaultFvPadFileNameGuid = { 0x78f54d4, 0xcc22, 0x4048, 0x9e, 0x94, 0x87, 0x9c, 0x21, 0x4d, 0x56, 0x2f };\r
+\r
+//\r
+// This data array will be located at the base of the Firmware Volume Header (FVH)\r
+// in the boot block.  It must not exceed 14 bytes of code.  The last 2 bytes\r
+// will be used to keep the FVH checksum consistent.\r
+// This code will be run in response to a starutp IPI for HT-enabled systems.\r
+//\r
+#define SIZEOF_STARTUP_DATA_ARRAY 0x10\r
+\r
+UINT8                                   m128kRecoveryStartupApDataArray[SIZEOF_STARTUP_DATA_ARRAY] = {\r
+  //\r
+  // EA D0 FF 00 F0               ; far jmp F000:FFD0\r
+  // 0, 0, 0, 0, 0, 0, 0, 0, 0,   ; Reserved bytes\r
+  // 0, 0                         ; Checksum Padding\r
+  //\r
+  0xEA,\r
+  0xD0,\r
+  0xFF,\r
+  0x0,\r
+  0xF0,\r
+  0x00,\r
+  0x00,\r
+  0x00,\r
+  0x00,\r
+  0x00,\r
+  0x00,\r
+  0x00,\r
+  0x00,\r
+  0x00,\r
+  0x00,\r
+  0x00\r
+};\r
+\r
+UINT8                                   m64kRecoveryStartupApDataArray[SIZEOF_STARTUP_DATA_ARRAY] = {\r
+  //\r
+  // EB CE                               ; jmp short ($-0x30)\r
+  // ; (from offset 0x0 to offset 0xFFD0)\r
+  // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ; Reserved bytes\r
+  // 0, 0                                ; Checksum Padding\r
+  //\r
+  0xEB,\r
+  0xCE,\r
+  0x00,\r
+  0x00,\r
+  0x00,\r
+  0x00,\r
+  0x00,\r
+  0x00,\r
+  0x00,\r
+  0x00,\r
+  0x00,\r
+  0x00,\r
+  0x00,\r
+  0x00,\r
+  0x00,\r
+  0x00\r
+};\r
+\r
+EFI_STATUS\r
+ParseFvInf (\r
+  IN MEMORY_FILE  *InfFile,\r
+  IN FV_INFO      *FvInfo\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  This function parses a FV.INF file and copies info into a FV_INFO structure.\r
+\r
+Arguments:\r
+\r
+  InfFile         Memory file image.\r
+  FvInfo          Information read from INF file.\r
+\r
+Returns:\r
+\r
+  EFI_SUCCESS       INF file information successfully retrieved.\r
+  EFI_ABORTED       INF file has an invalid format.\r
+  EFI_NOT_FOUND     A required string was not found in the INF file.\r
+--*/\r
+{\r
+  CHAR8       Value[_MAX_PATH];\r
+  UINT64      Value64;\r
+  UINTN       Index;\r
+  EFI_STATUS  Status;\r
+\r
+  //\r
+  // Initialize FV info\r
+  //\r
+  memset (FvInfo, 0, sizeof (FV_INFO));\r
+\r
+  //\r
+  // Read the FV base address\r
+  //\r
+  Status = FindToken (InfFile, OPTIONS_SECTION_STRING, EFI_FV_BASE_ADDRESS_STRING, 0, Value);\r
+\r
+  if (Status == EFI_SUCCESS) {\r
+    //\r
+    // Get the base address\r
+    //\r
+    Status = AsciiStringToUint64 (Value, FALSE, &Value64);\r
+    if (EFI_ERROR (Status)) {\r
+      Error (NULL, 0, 0, EFI_FV_BASE_ADDRESS_STRING, "invalid value");\r
+      return EFI_ABORTED;\r
+    }\r
+\r
+    FvInfo->BaseAddress = Value64;\r
+  } else {\r
+    Error (NULL, 0, 0, EFI_FV_BASE_ADDRESS_STRING, "could not find value");\r
+    return EFI_ABORTED;\r
+  }\r
+  //\r
+  // Read the FV Guid\r
+  //\r
+  Status = FindToken (InfFile, OPTIONS_SECTION_STRING, EFI_FV_GUID_STRING, 0, Value);\r
+\r
+  if (Status == EFI_SUCCESS) {\r
+    //\r
+    // Get the guid value\r
+    //\r
+    Status = StringToGuid (Value, &FvInfo->FvGuid);\r
+    if (EFI_ERROR (Status)) {\r
+      memcpy (&FvInfo->FvGuid, &FfsGuid, sizeof (EFI_GUID));\r
+    }\r
+  } else {\r
+    memcpy (&FvInfo->FvGuid, &FfsGuid, sizeof (EFI_GUID));\r
+  }\r
+  //\r
+  // Read the FV file name\r
+  //\r
+  Status = FindToken (InfFile, OPTIONS_SECTION_STRING, EFI_FV_FILE_NAME_STRING, 0, Value);\r
+\r
+  if (Status == EFI_SUCCESS) {\r
+    //\r
+    // copy the file name\r
+    //\r
+    strcpy (FvInfo->FvName, Value);\r
+  } else {\r
+    Error (NULL, 0, 0, EFI_FV_FILE_NAME_STRING, "value not specified");\r
+    return EFI_ABORTED;\r
+  }\r
+  //\r
+  // Read the Sym file name\r
+  //\r
+  Status = FindToken (InfFile, OPTIONS_SECTION_STRING, EFI_SYM_FILE_NAME_STRING, 0, Value);\r
+\r
+  if (Status == EFI_SUCCESS) {\r
+    //\r
+    // copy the file name\r
+    //\r
+    strcpy (FvInfo->SymName, Value);\r
+  } else {\r
+    //\r
+    // Symbols not required, so init to NULL.\r
+    //\r
+    strcpy (FvInfo->SymName, "");\r
+  }\r
+  //\r
+  // Read the read disabled capability attribute\r
+  //\r
+  Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_READ_DISABLED_CAP_STRING, 0, Value);\r
+\r
+  if (Status == EFI_SUCCESS) {\r
+    //\r
+    // Update the read disabled flag\r
+    //\r
+    if (strcmp (Value, TRUE_STRING) == 0) {\r
+      FvInfo->FvAttributes |= EFI_FVB_READ_DISABLED_CAP;\r
+    } else if (strcmp (Value, FALSE_STRING) != 0) {\r
+      Error (NULL, 0, 0, EFI_FVB_READ_DISABLED_CAP_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);\r
+      return EFI_ABORTED;\r
+    }\r
+  } else {\r
+    Error (NULL, 0, 0, EFI_FVB_READ_DISABLED_CAP_STRING, "value not specified");\r
+    return Status;\r
+  }\r
+  //\r
+  // Read the read enabled capability attribute\r
+  //\r
+  Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_READ_ENABLED_CAP_STRING, 0, Value);\r
+\r
+  if (Status == EFI_SUCCESS) {\r
+    //\r
+    // Update the read disabled flag\r
+    //\r
+    if (strcmp (Value, TRUE_STRING) == 0) {\r
+      FvInfo->FvAttributes |= EFI_FVB_READ_ENABLED_CAP;\r
+    } else if (strcmp (Value, FALSE_STRING) != 0) {\r
+      Error (NULL, 0, 0, EFI_FVB_READ_ENABLED_CAP_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);\r
+      return EFI_ABORTED;\r
+    }\r
+  } else {\r
+    Error (NULL, 0, 0, EFI_FVB_READ_ENABLED_CAP_STRING, "value not specified");\r
+    return Status;\r
+  }\r
+  //\r
+  // Read the read status attribute\r
+  //\r
+  Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_READ_STATUS_STRING, 0, Value);\r
+\r
+  if (Status == EFI_SUCCESS) {\r
+    //\r
+    // Update the read disabled flag\r
+    //\r
+    if (strcmp (Value, TRUE_STRING) == 0) {\r
+      FvInfo->FvAttributes |= EFI_FVB_READ_STATUS;\r
+    } else if (strcmp (Value, FALSE_STRING) != 0) {\r
+      Error (NULL, 0, 0, EFI_FVB_READ_STATUS_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);\r
+      return EFI_ABORTED;\r
+    }\r
+  } else {\r
+    Error (NULL, 0, 0, EFI_FVB_READ_STATUS_STRING, "value not specified");\r
+    return Status;\r
+  }\r
+  //\r
+  // Read the write disabled capability attribute\r
+  //\r
+  Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_WRITE_DISABLED_CAP_STRING, 0, Value);\r
+\r
+  if (Status == EFI_SUCCESS) {\r
+    //\r
+    // Update the write disabled flag\r
+    //\r
+    if (strcmp (Value, TRUE_STRING) == 0) {\r
+      FvInfo->FvAttributes |= EFI_FVB_WRITE_DISABLED_CAP;\r
+    } else if (strcmp (Value, FALSE_STRING) != 0) {\r
+      Error (NULL, 0, 0, EFI_FVB_WRITE_DISABLED_CAP_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);\r
+      return EFI_ABORTED;\r
+    }\r
+  } else {\r
+    Error (NULL, 0, 0, EFI_FVB_WRITE_DISABLED_CAP_STRING, "value not specified");\r
+    return Status;\r
+  }\r
+  //\r
+  // Read the write enabled capability attribute\r
+  //\r
+  Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_WRITE_ENABLED_CAP_STRING, 0, Value);\r
+\r
+  if (Status == EFI_SUCCESS) {\r
+    //\r
+    // Update the write disabled flag\r
+    //\r
+    if (strcmp (Value, TRUE_STRING) == 0) {\r
+      FvInfo->FvAttributes |= EFI_FVB_WRITE_ENABLED_CAP;\r
+    } else if (strcmp (Value, FALSE_STRING) != 0) {\r
+      Error (NULL, 0, 0, EFI_FVB_WRITE_ENABLED_CAP_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);\r
+      return EFI_ABORTED;\r
+    }\r
+  } else {\r
+    Error (NULL, 0, 0, EFI_FVB_WRITE_ENABLED_CAP_STRING, "value not specified");\r
+    return Status;\r
+  }\r
+  //\r
+  // Read the write status attribute\r
+  //\r
+  Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_WRITE_STATUS_STRING, 0, Value);\r
+\r
+  if (Status == EFI_SUCCESS) {\r
+    //\r
+    // Update the write disabled flag\r
+    //\r
+    if (strcmp (Value, TRUE_STRING) == 0) {\r
+      FvInfo->FvAttributes |= EFI_FVB_WRITE_STATUS;\r
+    } else if (strcmp (Value, FALSE_STRING) != 0) {\r
+      Error (NULL, 0, 0, EFI_FVB_WRITE_STATUS_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);\r
+      return EFI_ABORTED;\r
+    }\r
+  } else {\r
+    Error (NULL, 0, 0, EFI_FVB_WRITE_STATUS_STRING, "value not specified");\r
+    return Status;\r
+  }\r
+  //\r
+  // Read the lock capability attribute\r
+  //\r
+  Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_LOCK_CAP_STRING, 0, Value);\r
+\r
+  if (Status == EFI_SUCCESS) {\r
+    //\r
+    // Update the attribute flag\r
+    //\r
+    if (strcmp (Value, TRUE_STRING) == 0) {\r
+      FvInfo->FvAttributes |= EFI_FVB_LOCK_CAP;\r
+    } else if (strcmp (Value, FALSE_STRING) != 0) {\r
+      Error (NULL, 0, 0, EFI_FVB_LOCK_CAP_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);\r
+      return EFI_ABORTED;\r
+    }\r
+  } else {\r
+    Error (NULL, 0, 0, EFI_FVB_LOCK_CAP_STRING, "value not specified");\r
+    return Status;\r
+  }\r
+  //\r
+  // Read the lock status attribute\r
+  //\r
+  Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_LOCK_STATUS_STRING, 0, Value);\r
+\r
+  if (Status == EFI_SUCCESS) {\r
+    //\r
+    // Update the attribute flag\r
+    //\r
+    if (strcmp (Value, TRUE_STRING) == 0) {\r
+      FvInfo->FvAttributes |= EFI_FVB_LOCK_STATUS;\r
+    } else if (strcmp (Value, FALSE_STRING) != 0) {\r
+      Error (NULL, 0, 0, EFI_FVB_LOCK_STATUS_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);\r
+      return EFI_ABORTED;\r
+    }\r
+  } else {\r
+    Error (NULL, 0, 0, EFI_FVB_LOCK_STATUS_STRING, "value not specified");\r
+    return Status;\r
+  }\r
+  //\r
+  // Read the sticky write attribute\r
+  //\r
+  Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_STICKY_WRITE_STRING, 0, Value);\r
+\r
+  if (Status == EFI_SUCCESS) {\r
+    //\r
+    // Update the attribute flag\r
+    //\r
+    if (strcmp (Value, TRUE_STRING) == 0) {\r
+      FvInfo->FvAttributes |= EFI_FVB_STICKY_WRITE;\r
+    } else if (strcmp (Value, FALSE_STRING) != 0) {\r
+      Error (NULL, 0, 0, EFI_FVB_STICKY_WRITE_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);\r
+      return EFI_ABORTED;\r
+    }\r
+  } else {\r
+    Error (NULL, 0, 0, EFI_FVB_STICKY_WRITE_STRING, "value not specified");\r
+    return Status;\r
+  }\r
+  //\r
+  // Read the memory mapped attribute\r
+  //\r
+  Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_MEMORY_MAPPED_STRING, 0, Value);\r
+\r
+  if (Status == EFI_SUCCESS) {\r
+    //\r
+    // Update the attribute flag\r
+    //\r
+    if (strcmp (Value, TRUE_STRING) == 0) {\r
+      FvInfo->FvAttributes |= EFI_FVB_MEMORY_MAPPED;\r
+    } else if (strcmp (Value, FALSE_STRING) != 0) {\r
+      Error (NULL, 0, 0, EFI_FVB_MEMORY_MAPPED_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);\r
+      return EFI_ABORTED;\r
+    }\r
+  } else {\r
+    Error (NULL, 0, 0, EFI_FVB_MEMORY_MAPPED_STRING, "value not specified");\r
+    return Status;\r
+  }\r
+  //\r
+  // Read the erase polarity attribute\r
+  //\r
+  Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ERASE_POLARITY_STRING, 0, Value);\r
+\r
+  if (Status == EFI_SUCCESS) {\r
+    //\r
+    // Update the attribute flag\r
+    //\r
+    if (strcmp (Value, ONE_STRING) == 0) {\r
+      FvInfo->FvAttributes |= EFI_FVB_ERASE_POLARITY;\r
+    } else if (strcmp (Value, ZERO_STRING) != 0) {\r
+      Error (NULL, 0, 0, EFI_FVB_ERASE_POLARITY_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);\r
+      return EFI_ABORTED;\r
+    }\r
+  } else {\r
+    Error (NULL, 0, 0, EFI_FVB_ERASE_POLARITY_STRING, "value not specified");\r
+    return Status;\r
+  }\r
+\r
+#if (PI_SPECIFICATION_VERSION >= 0x00010000)        \r
+  //\r
+  // Read the read lock capability attribute\r
+  //\r
+  Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_READ_LOCK_CAP_STRING, 0, Value);\r
+\r
+  if (Status == EFI_SUCCESS) {\r
+    //\r
+    // Update attribute\r
+    //\r
+    if (strcmp (Value, TRUE_STRING) == 0) {\r
+      FvInfo->FvAttributes |= EFI_FVB2_READ_LOCK_CAP;\r
+    } else if (strcmp (Value, FALSE_STRING) != 0) {\r
+      Error (NULL, 0, 0, EFI_FVB_READ_LOCK_CAP_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);\r
+      return EFI_ABORTED;\r
+    }\r
+  } else {\r
+    Error (NULL, 0, 0, EFI_FVB_READ_LOCK_CAP_STRING, "value not specified");\r
+    return Status;\r
+  }\r
+\r
+  //\r
+  // Read the read lock status attribute\r
+  //\r
+  Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_READ_LOCK_STATUS_STRING, 0, Value);\r
+\r
+  if (Status == EFI_SUCCESS) {\r
+    //\r
+    // Update attribute\r
+    //\r
+    if (strcmp (Value, TRUE_STRING) == 0) {\r
+      FvInfo->FvAttributes |= EFI_FVB2_READ_LOCK_STATUS;\r
+    } else if (strcmp (Value, FALSE_STRING) != 0) {\r
+      Error (NULL, 0, 0, EFI_FVB_READ_LOCK_STATUS_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);\r
+      return EFI_ABORTED;\r
+    }\r
+  } else {\r
+    Error (NULL, 0, 0, EFI_FVB_READ_LOCK_STATUS_STRING, "value not specified");\r
+    return Status;\r
+  }\r
+\r
+  //\r
+  // Read the write lock capability attribute\r
+  //\r
+  Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_WRITE_LOCK_CAP_STRING, 0, Value);\r
+\r
+  if (Status == EFI_SUCCESS) {\r
+    //\r
+    // Update attribute\r
+    //\r
+    if (strcmp (Value, TRUE_STRING) == 0) {\r
+      FvInfo->FvAttributes |= EFI_FVB2_WRITE_LOCK_CAP;\r
+    } else if (strcmp (Value, FALSE_STRING) != 0) {\r
+      Error (NULL, 0, 0, EFI_FVB_WRITE_LOCK_CAP_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);\r
+      return EFI_ABORTED;\r
+    }\r
+  } else {\r
+    Error (NULL, 0, 0, EFI_FVB_WRITE_LOCK_CAP_STRING, "value not specified");\r
+    return Status;\r
+  }\r
+\r
+  //\r
+  // Read the write lock status attribute\r
+  //\r
+  Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_WRITE_LOCK_STATUS_STRING, 0, Value);\r
+\r
+  if (Status == EFI_SUCCESS) {\r
+    //\r
+    // Update attribute\r
+    //\r
+    if (strcmp (Value, TRUE_STRING) == 0) {\r
+      FvInfo->FvAttributes |= EFI_FVB2_WRITE_LOCK_STATUS;\r
+    } else if (strcmp (Value, FALSE_STRING) != 0) {\r
+      Error (NULL, 0, 0, EFI_FVB_WRITE_LOCK_STATUS_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);\r
+      return EFI_ABORTED;\r
+    }\r
+  } else {\r
+    Error (NULL, 0, 0, EFI_FVB_WRITE_LOCK_STATUS_STRING, "value not specified");\r
+    return Status;\r
+  }\r
+#endif\r
+\r
+#if (PI_SPECIFICATION_VERSION < 0x00010000)     \r
+  //\r
+  // Read the alignment capabilities attribute\r
+  //\r
+  Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ALIGNMENT_CAP_STRING, 0, Value);\r
+\r
+  if (Status == EFI_SUCCESS) {\r
+    //\r
+    // Update attribute\r
+    //\r
+    if (strcmp (Value, TRUE_STRING) == 0) {\r
+      FvInfo->FvAttributes |= EFI_FVB_ALIGNMENT_CAP;\r
+    } else if (strcmp (Value, FALSE_STRING) != 0) {\r
+      Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_CAP_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);\r
+      return EFI_ABORTED;\r
+    }\r
+  } else {\r
+    Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_CAP_STRING, "value not specified");\r
+    return Status;\r
+  }\r
+\r
+  //\r
+  // Read the word alignment capability attribute\r
+  //\r
+  Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ALIGNMENT_2_STRING, 0, Value);\r
+\r
+  if (Status == EFI_SUCCESS) {\r
+    //\r
+    // Update attribute\r
+    //\r
+    if (strcmp (Value, TRUE_STRING) == 0) {\r
+      FvInfo->FvAttributes |= EFI_FVB_ALIGNMENT_2;\r
+    } else if (strcmp (Value, FALSE_STRING) != 0) {\r
+      Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_2_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);\r
+      return EFI_ABORTED;\r
+    }\r
+  } else {\r
+    Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_2_STRING, "value not specified");\r
+    return Status;\r
+  }\r
+\r
+  \r
+  //\r
+  // Read the dword alignment capability attribute\r
+  //\r
+  Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ALIGNMENT_4_STRING, 0, Value);\r
+\r
+  if (Status == EFI_SUCCESS) {\r
+    //\r
+    // Update attribute\r
+    //\r
+    if (strcmp (Value, TRUE_STRING) == 0) {\r
+      FvInfo->FvAttributes |= EFI_FVB_ALIGNMENT_4;\r
+    } else if (strcmp (Value, FALSE_STRING) != 0) {\r
+      Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_4_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);\r
+      return EFI_ABORTED;\r
+    }\r
+  } else {\r
+    Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_4_STRING, "value not specified");\r
+    return Status;\r
+  }\r
+  //\r
+  // Read the word alignment capability attribute\r
+  //\r
+  Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ALIGNMENT_8_STRING, 0, Value);\r
+\r
+  if (Status == EFI_SUCCESS) {\r
+    //\r
+    // Update attribute\r
+    //\r
+    if (strcmp (Value, TRUE_STRING) == 0) {\r
+      FvInfo->FvAttributes |= EFI_FVB_ALIGNMENT_8;\r
+    } else if (strcmp (Value, FALSE_STRING) != 0) {\r
+      Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_8_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);\r
+      return EFI_ABORTED;\r
+    }\r
+  } else {\r
+    Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_8_STRING, "value not specified");\r
+    return Status;\r
+  }\r
+  //\r
+  // Read the qword alignment capability attribute\r
+  //\r
+  Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ALIGNMENT_16_STRING, 0, Value);\r
+\r
+  if (Status == EFI_SUCCESS) {\r
+    //\r
+    // Update attribute\r
+    //\r
+    if (strcmp (Value, TRUE_STRING) == 0) {\r
+      FvInfo->FvAttributes |= EFI_FVB_ALIGNMENT_16;\r
+    } else if (strcmp (Value, FALSE_STRING) != 0) {\r
+      Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_16_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);\r
+      return EFI_ABORTED;\r
+    }\r
+  } else {\r
+    Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_16_STRING, "value not specified");\r
+    return Status;\r
+  }\r
+  //\r
+  // Read the 32 byte alignment capability attribute\r
+  //\r
+  Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ALIGNMENT_32_STRING, 0, Value);\r
+\r
+  if (Status == EFI_SUCCESS) {\r
+    //\r
+    // Update attribute\r
+    //\r
+    if (strcmp (Value, TRUE_STRING) == 0) {\r
+      FvInfo->FvAttributes |= EFI_FVB_ALIGNMENT_32;\r
+    } else if (strcmp (Value, FALSE_STRING) != 0) {\r
+      Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_32_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);\r
+      return EFI_ABORTED;\r
+    }\r
+  } else {\r
+    Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_32_STRING, "value not specified");\r
+    return Status;\r
+  }\r
+  //\r
+  // Read the 64 byte alignment capability attribute\r
+  //\r
+  Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ALIGNMENT_64_STRING, 0, Value);\r
+\r
+  if (Status == EFI_SUCCESS) {\r
+    //\r
+    // Update attribute\r
+    //\r
+    if (strcmp (Value, TRUE_STRING) == 0) {\r
+      FvInfo->FvAttributes |= EFI_FVB_ALIGNMENT_64;\r
+    } else if (strcmp (Value, FALSE_STRING) != 0) {\r
+      Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_64_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);\r
+      return EFI_ABORTED;\r
+    }\r
+  } else {\r
+    Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_64_STRING, "value not specified");\r
+    return Status;\r
+  }\r
+  //\r
+  // Read the 128 byte alignment capability attribute\r
+  //\r
+  Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ALIGNMENT_128_STRING, 0, Value);\r
+\r
+  if (Status == EFI_SUCCESS) {\r
+    //\r
+    // Update attribute\r
+    //\r
+    if (strcmp (Value, TRUE_STRING) == 0) {\r
+      FvInfo->FvAttributes |= EFI_FVB_ALIGNMENT_128;\r
+    } else if (strcmp (Value, FALSE_STRING) != 0) {\r
+      Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_128_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);\r
+      return EFI_ABORTED;\r
+    }\r
+  } else {\r
+    Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_128_STRING, "value not specified");\r
+    return Status;\r
+  }\r
+  //\r
+  // Read the 256 byte alignment capability attribute\r
+  //\r
+  Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ALIGNMENT_256_STRING, 0, Value);\r
+\r
+  if (Status == EFI_SUCCESS) {\r
+    //\r
+    // Update attribute\r
+    //\r
+    if (strcmp (Value, TRUE_STRING) == 0) {\r
+      FvInfo->FvAttributes |= EFI_FVB_ALIGNMENT_256;\r
+    } else if (strcmp (Value, FALSE_STRING) != 0) {\r
+      Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_256_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);\r
+      return EFI_ABORTED;\r
+    }\r
+  } else {\r
+    Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_256_STRING, "value not specified");\r
+    return Status;\r
+  }\r
+  //\r
+  // Read the 512 byte alignment capability attribute\r
+  //\r
+  Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ALIGNMENT_512_STRING, 0, Value);\r
+\r
+  if (Status == EFI_SUCCESS) {\r
+    //\r
+    // Update attribute\r
+    //\r
+    if (strcmp (Value, TRUE_STRING) == 0) {\r
+      FvInfo->FvAttributes |= EFI_FVB_ALIGNMENT_512;\r
+    } else if (strcmp (Value, FALSE_STRING) != 0) {\r
+      Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_512_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);\r
+      return EFI_ABORTED;\r
+    }\r
+  } else {\r
+    Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_512_STRING, "value not specified");\r
+    return Status;\r
+  }\r
+  //\r
+  // Read the 1K byte alignment capability attribute\r
+  //\r
+  Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ALIGNMENT_1K_STRING, 0, Value);\r
+\r
+  if (Status == EFI_SUCCESS) {\r
+    //\r
+    // Update attribute\r
+    //\r
+    if (strcmp (Value, TRUE_STRING) == 0) {\r
+      FvInfo->FvAttributes |= EFI_FVB_ALIGNMENT_1K;\r
+    } else if (strcmp (Value, FALSE_STRING) != 0) {\r
+      Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_1K_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);\r
+      return EFI_ABORTED;\r
+    }\r
+  } else {\r
+    Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_1K_STRING, "value not specified");\r
+    return Status;\r
+  }\r
+  //\r
+  // Read the 2K byte alignment capability attribute\r
+  //\r
+  Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ALIGNMENT_2K_STRING, 0, Value);\r
+\r
+  if (Status == EFI_SUCCESS) {\r
+    //\r
+    // Update attribute\r
+    //\r
+    if (strcmp (Value, TRUE_STRING) == 0) {\r
+      FvInfo->FvAttributes |= EFI_FVB_ALIGNMENT_2K;\r
+    } else if (strcmp (Value, FALSE_STRING) != 0) {\r
+      Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_2K_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);\r
+      return EFI_ABORTED;\r
+    }\r
+  } else {\r
+    Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_2K_STRING, "value not specified");\r
+    return Status;\r
+  }\r
+  //\r
+  // Read the 4K byte alignment capability attribute\r
+  //\r
+  Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ALIGNMENT_4K_STRING, 0, Value);\r
+\r
+  if (Status == EFI_SUCCESS) {\r
+    //\r
+    // Update attribute\r
+    //\r
+    if (strcmp (Value, TRUE_STRING) == 0) {\r
+      FvInfo->FvAttributes |= EFI_FVB_ALIGNMENT_4K;\r
+    } else if (strcmp (Value, FALSE_STRING) != 0) {\r
+      Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_4K_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);\r
+      return EFI_ABORTED;\r
+    }\r
+  } else {\r
+    Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_4K_STRING, "value not specified");\r
+    return Status;\r
+  }\r
+  //\r
+  // Read the 8K byte alignment capability attribute\r
+  //\r
+  Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ALIGNMENT_8K_STRING, 0, Value);\r
+\r
+  if (Status == EFI_SUCCESS) {\r
+    //\r
+    // Update attribute\r
+    //\r
+    if (strcmp (Value, TRUE_STRING) == 0) {\r
+      FvInfo->FvAttributes |= EFI_FVB_ALIGNMENT_8K;\r
+    } else if (strcmp (Value, FALSE_STRING) != 0) {\r
+      Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_8K_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);\r
+      return EFI_ABORTED;\r
+    }\r
+  } else {\r
+    Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_8K_STRING, "value not specified");\r
+    return Status;\r
+  }\r
+  //\r
+  // Read the 16K byte alignment capability attribute\r
+  //\r
+  Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ALIGNMENT_16K_STRING, 0, Value);\r
+\r
+  if (Status == EFI_SUCCESS) {\r
+    //\r
+    // Update attribute\r
+    //\r
+    if (strcmp (Value, TRUE_STRING) == 0) {\r
+      FvInfo->FvAttributes |= EFI_FVB_ALIGNMENT_16K;\r
+    } else if (strcmp (Value, FALSE_STRING) != 0) {\r
+      Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_16K_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);\r
+      return EFI_ABORTED;\r
+    }\r
+  } else {\r
+    Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_16K_STRING, "value not specified");\r
+    return Status;\r
+  }\r
+  //\r
+  // Read the 32K byte alignment capability attribute\r
+  //\r
+  Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ALIGNMENT_32K_STRING, 0, Value);\r
+\r
+  if (Status == EFI_SUCCESS) {\r
+    //\r
+    // Update attribute\r
+    //\r
+    if (strcmp (Value, TRUE_STRING) == 0) {\r
+      FvInfo->FvAttributes |= EFI_FVB_ALIGNMENT_32K;\r
+    } else if (strcmp (Value, FALSE_STRING) != 0) {\r
+      Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_32K_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);\r
+      return EFI_ABORTED;\r
+    }\r
+  } else {\r
+    Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_32K_STRING, "value not specified");\r
+    return Status;\r
+  }\r
+  //\r
+  // Read the 64K byte alignment capability attribute\r
+  //\r
+  Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ALIGNMENT_64K_STRING, 0, Value);\r
+\r
+  if (Status == EFI_SUCCESS) {\r
+    //\r
+    // Update attribute\r
+    //\r
+    if (strcmp (Value, TRUE_STRING) == 0) {\r
+      FvInfo->FvAttributes |= EFI_FVB_ALIGNMENT_64K;\r
+    } else if (strcmp (Value, FALSE_STRING) != 0) {\r
+      Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_64K_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);\r
+      return EFI_ABORTED;\r
+    }\r
+  } else {\r
+    Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_64K_STRING, "value not specified");\r
+    return Status;\r
+  }\r
+\r
+  if (!(FvInfo->FvAttributes & EFI_FVB_ALIGNMENT_CAP) &&\r
+      (\r
+        (FvInfo->FvAttributes & EFI_FVB_ALIGNMENT_2) ||\r
+        (FvInfo->FvAttributes & EFI_FVB_ALIGNMENT_4) ||\r
+        (FvInfo->FvAttributes & EFI_FVB_ALIGNMENT_8) ||\r
+        (FvInfo->FvAttributes & EFI_FVB_ALIGNMENT_16) ||\r
+        (FvInfo->FvAttributes & EFI_FVB_ALIGNMENT_32) ||\r
+        (FvInfo->FvAttributes & EFI_FVB_ALIGNMENT_64) ||\r
+        (FvInfo->FvAttributes & EFI_FVB_ALIGNMENT_128) ||\r
+        (FvInfo->FvAttributes & EFI_FVB_ALIGNMENT_256) ||\r
+        (FvInfo->FvAttributes & EFI_FVB_ALIGNMENT_512) ||\r
+        (FvInfo->FvAttributes & EFI_FVB_ALIGNMENT_1K) ||\r
+        (FvInfo->FvAttributes & EFI_FVB_ALIGNMENT_2K) ||\r
+        (FvInfo->FvAttributes & EFI_FVB_ALIGNMENT_4K) ||\r
+        (FvInfo->FvAttributes & EFI_FVB_ALIGNMENT_8K) ||\r
+        (FvInfo->FvAttributes & EFI_FVB_ALIGNMENT_16K) ||\r
+        (FvInfo->FvAttributes & EFI_FVB_ALIGNMENT_32K) ||\r
+        (FvInfo->FvAttributes & EFI_FVB_ALIGNMENT_64K)\r
+      )\r
+     ){\r
+    Error (\r
+      NULL,\r
+      0,\r
+      0,\r
+      "illegal combination of alignment attributes",\r
+      "if %s is not %s, no individual alignments can be %s",\r
+      EFI_FVB_ALIGNMENT_CAP_STRING,\r
+      TRUE_STRING,\r
+      TRUE_STRING\r
+      );\r
+    return EFI_ABORTED;\r
+  }\r
+#else\r
+  //\r
+  // Read the PI1.0 FVB2 Alignment Capabilities Attribute\r
+  //\r
+  Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB2_ALIGNMENT_STRING, 0, Value);\r
+\r
+  if (Status == EFI_SUCCESS) {\r
+    //\r
+    // Update attribute\r
+    //\r
+    if (strcmp (Value, EFI_FVB2_ALIGNMENT_1_STRING) == 0) {\r
+      FvInfo->FvAttributes |= EFI_FVB2_ALIGNMENT_1;\r
+    } else if (strcmp (Value, EFI_FVB2_ALIGNMENT_2_STRING) == 0) {\r
+      FvInfo->FvAttributes |= EFI_FVB2_ALIGNMENT_2;\r
+    } else if (strcmp (Value, EFI_FVB2_ALIGNMENT_4_STRING) == 0) {\r
+      FvInfo->FvAttributes |= EFI_FVB2_ALIGNMENT_4;\r
+    } else if (strcmp (Value, EFI_FVB2_ALIGNMENT_8_STRING) == 0) {\r
+      FvInfo->FvAttributes |= EFI_FVB2_ALIGNMENT_8;\r
+    } else if (strcmp (Value, EFI_FVB2_ALIGNMENT_16_STRING) == 0) {\r
+      FvInfo->FvAttributes |= EFI_FVB2_ALIGNMENT_16;\r
+    } else if (strcmp (Value, EFI_FVB2_ALIGNMENT_32_STRING) == 0) {\r
+      FvInfo->FvAttributes |= EFI_FVB2_ALIGNMENT_32;\r
+    } else if (strcmp (Value, EFI_FVB2_ALIGNMENT_64_STRING) == 0) {\r
+      FvInfo->FvAttributes |= EFI_FVB2_ALIGNMENT_64;\r
+    } else if (strcmp (Value, EFI_FVB2_ALIGNMENT_128_STRING) == 0) {\r
+      FvInfo->FvAttributes |= EFI_FVB2_ALIGNMENT_128;\r
+    } else if (strcmp (Value, EFI_FVB2_ALIGNMENT_256_STRING) == 0) {\r
+      FvInfo->FvAttributes |= EFI_FVB2_ALIGNMENT_256;\r
+    } else if (strcmp (Value, EFI_FVB2_ALIGNMENT_512_STRING) == 0) {\r
+      FvInfo->FvAttributes |= EFI_FVB2_ALIGNMENT_512;\r
+    } else if (strcmp (Value, EFI_FVB2_ALIGNMENT_1K_STRING) == 0) {\r
+      FvInfo->FvAttributes |= EFI_FVB2_ALIGNMENT_1K;\r
+    } else if (strcmp (Value, EFI_FVB2_ALIGNMENT_2K_STRING) == 0) {\r
+      FvInfo->FvAttributes |= EFI_FVB2_ALIGNMENT_2K;\r
+    } else if (strcmp (Value, EFI_FVB2_ALIGNMENT_4K_STRING) == 0) {\r
+      FvInfo->FvAttributes |= EFI_FVB2_ALIGNMENT_4K;\r
+    } else if (strcmp (Value, EFI_FVB2_ALIGNMENT_8K_STRING) == 0) {\r
+      FvInfo->FvAttributes |= EFI_FVB2_ALIGNMENT_8K;\r
+    } else if (strcmp (Value, EFI_FVB2_ALIGNMENT_16K_STRING) == 0) {\r
+      FvInfo->FvAttributes |= EFI_FVB2_ALIGNMENT_16K;\r
+    } else if (strcmp (Value, EFI_FVB2_ALIGNMENT_32K_STRING) == 0) {\r
+      FvInfo->FvAttributes |= EFI_FVB2_ALIGNMENT_32K;\r
+    } else if (strcmp (Value, EFI_FVB2_ALIGNMENT_64K_STRING) == 0) {\r
+      FvInfo->FvAttributes |= EFI_FVB2_ALIGNMENT_64K;\r
+    } else if (strcmp (Value, EFI_FVB2_ALIGNMENT_128K_STRING) == 0) {\r
+      FvInfo->FvAttributes |= EFI_FVB2_ALIGNMENT_128K;\r
+    } else if (strcmp (Value, EFI_FVB2_ALIGNMENT_256K_STRING) == 0) {\r
+      FvInfo->FvAttributes |= EFI_FVB2_ALIGNMENT_256K;\r
+    } else if (strcmp (Value, EFI_FVB2_ALIGNMENT_512K_STRING) == 0) {\r
+      FvInfo->FvAttributes |= EFI_FVB2_ALIGNMNET_512K;\r
+    } else if (strcmp (Value, EFI_FVB2_ALIGNMENT_1M_STRING) == 0) {\r
+      FvInfo->FvAttributes |= EFI_FVB2_ALIGNMENT_1M;\r
+    } else if (strcmp (Value, EFI_FVB2_ALIGNMENT_2M_STRING) == 0) {\r
+      FvInfo->FvAttributes |= EFI_FVB2_ALIGNMENT_2M;\r
+    } else if (strcmp (Value, EFI_FVB2_ALIGNMENT_4M_STRING) == 0) {\r
+      FvInfo->FvAttributes |= EFI_FVB2_ALIGNMENT_4M;\r
+    } else if (strcmp (Value, EFI_FVB2_ALIGNMENT_8M_STRING) == 0) {\r
+      FvInfo->FvAttributes |= EFI_FVB2_ALIGNMENT_8M;\r
+    } else if (strcmp (Value, EFI_FVB2_ALIGNMENT_16M_STRING) == 0) {\r
+      FvInfo->FvAttributes |= EFI_FVB2_ALIGNMENT_16M;\r
+    } else if (strcmp (Value, EFI_FVB2_ALIGNMENT_32M_STRING) == 0) {\r
+      FvInfo->FvAttributes |= EFI_FVB2_ALIGNMENT_32M;\r
+    } else if (strcmp (Value, EFI_FVB2_ALIGNMENT_64M_STRING) == 0) {\r
+      FvInfo->FvAttributes |= EFI_FVB2_ALIGNMENT_64M;\r
+    } else if (strcmp (Value, EFI_FVB2_ALIGNMENT_128M_STRING) == 0) {\r
+      FvInfo->FvAttributes |= EFI_FVB2_ALIGNMENT_128M;\r
+    } else if (strcmp (Value, EFI_FVB2_ALIGNMENT_256M_STRING) == 0) {\r
+      FvInfo->FvAttributes |= EFI_FVB2_ALIGNMENT_256M;\r
+    } else if (strcmp (Value, EFI_FVB2_ALIGNMENT_512M_STRING) == 0) {\r
+      FvInfo->FvAttributes |= EFI_FVB2_ALIGNMENT_512M;\r
+    } else if (strcmp (Value, EFI_FVB2_ALIGNMENT_1G_STRING) == 0) {\r
+      FvInfo->FvAttributes |= EFI_FVB2_ALIGNMENT_1G;\r
+    } else if (strcmp (Value, EFI_FVB2_ALIGNMENT_2G_STRING) == 0) {\r
+      FvInfo->FvAttributes |= EFI_FVB2_ALIGNMENT_2G;\r
+    } else {\r
+      Error (NULL, 0, 0, EFI_FVB2_ALIGNMENT_STRING, "value not correct!");\r
+      return EFI_ABORTED;\r
+    }\r
+  } else {\r
+    Error (NULL, 0, 0, EFI_FVB2_ALIGNMENT_STRING, "value not specified");\r
+    return Status;\r
+  }\r
+\r
+#endif  \r
+  //\r
+  // Read block maps\r
+  //\r
+  for (Index = 0; Index < MAX_NUMBER_OF_FV_BLOCKS; Index++) {\r
+    //\r
+    // Read the number of blocks\r
+    //\r
+    Status = FindToken (InfFile, OPTIONS_SECTION_STRING, EFI_NUM_BLOCKS_STRING, Index, Value);\r
+\r
+    if (Status == EFI_SUCCESS) {\r
+      //\r
+      // Update the number of blocks\r
+      //\r
+      Status = AsciiStringToUint64 (Value, FALSE, &Value64);\r
+      if (EFI_ERROR (Status)) {\r
+        Error (NULL, 0, 0, Value, "invalid value for %s", EFI_NUM_BLOCKS_STRING);\r
+        return EFI_ABORTED;\r
+      }\r
+\r
+      FvInfo->FvBlocks[Index].NumBlocks = (UINT32) Value64;\r
+    } else {\r
+      //\r
+      // If there is no number of blocks, but there is a size, then we have a mismatched pair\r
+      // and should return an error.\r
+      //\r
+      Status = FindToken (InfFile, OPTIONS_SECTION_STRING, EFI_BLOCK_SIZE_STRING, Index, Value);\r
+      if (!EFI_ERROR (Status)) {\r
+        Error (NULL, 0, 0, "must specify both", "%s and %s", EFI_NUM_BLOCKS_STRING, EFI_BLOCK_SIZE_STRING);\r
+        return EFI_ABORTED;\r
+      } else {\r
+        //\r
+        // We are done\r
+        //\r
+        break;\r
+      }\r
+    }\r
+    //\r
+    // Read the size of blocks\r
+    //\r
+    Status = FindToken (InfFile, OPTIONS_SECTION_STRING, EFI_BLOCK_SIZE_STRING, Index, Value);\r
+\r
+    if (Status == EFI_SUCCESS) {\r
+      //\r
+      // Update the number of blocks\r
+      //\r
+      Status = AsciiStringToUint64 (Value, FALSE, &Value64);\r
+      if (EFI_ERROR (Status)) {\r
+        Error (NULL, 0, 0, Value, "invalid value specified for %s", EFI_BLOCK_SIZE_STRING);\r
+        return EFI_ABORTED;\r
+      }\r
+\r
+      FvInfo->FvBlocks[Index].BlockLength = (UINT32) Value64;\r
+    } else {\r
+      //\r
+      // There is a number of blocks, but there is no size, so we have a mismatched pair\r
+      // and should return an error.\r
+      //\r
+      Error (NULL, 0, 0, "must specify both", "%s and %s", EFI_NUM_BLOCKS_STRING, EFI_BLOCK_SIZE_STRING);\r
+      return EFI_ABORTED;\r
+    }\r
+  }\r
+  //\r
+  // Read files\r
+  //\r
+  for (Index = 0; Index < MAX_NUMBER_OF_FILES_IN_FV; Index++) {\r
+    //\r
+    // Read the number of blocks\r
+    //\r
+    Status = FindToken (InfFile, FILES_SECTION_STRING, EFI_FILE_NAME_STRING, Index, Value);\r
+\r
+    if (Status == EFI_SUCCESS) {\r
+      //\r
+      // Add the file\r
+      //\r
+      strcpy (FvInfo->FvFiles[Index], Value);\r
+    } else {\r
+      break;\r
+    }\r
+  }\r
+\r
+  if (FindSection (InfFile, COMPONENT_SECTION_STRING)) {\r
+    Index = 0;\r
+    //\r
+    // Read component FV_VARIABLE\r
+    //\r
+    Status = FindToken (InfFile, COMPONENT_SECTION_STRING, EFI_NV_VARIABLE_STRING, 0, Value);\r
+\r
+    if (Status == EFI_SUCCESS) {\r
+      //\r
+      // Add the component\r
+      //\r
+      strcpy (FvInfo->FvComponents[Index].ComponentName, EFI_NV_VARIABLE_STRING);\r
+      Status = AsciiStringToUint64 (Value, FALSE, &Value64);\r
+      if (EFI_ERROR (Status)) {\r
+        printf ("ERROR: %s is not a valid integer.\n", EFI_NV_VARIABLE_STRING);\r
+        return EFI_ABORTED;\r
+      }\r
+\r
+      FvInfo->FvComponents[Index].Size = (UINTN) Value64;\r
+    } else {\r
+      printf ("WARNING: Could not read %s.\n", EFI_NV_VARIABLE_STRING);\r
+    }\r
+\r
+    Index++;\r
+    //\r
+    // Read component FV_EVENT_LOG\r
+    //\r
+    Status = FindToken (InfFile, COMPONENT_SECTION_STRING, EFI_NV_EVENT_LOG_STRING, 0, Value);\r
+\r
+    if (Status == EFI_SUCCESS) {\r
+      //\r
+      // Add the component\r
+      //\r
+      strcpy (FvInfo->FvComponents[Index].ComponentName, EFI_NV_EVENT_LOG_STRING);\r
+      Status = AsciiStringToUint64 (Value, FALSE, &Value64);\r
+      if (EFI_ERROR (Status)) {\r
+        printf ("ERROR: %s is not a valid integer.\n", EFI_NV_EVENT_LOG_STRING);\r
+        return EFI_ABORTED;\r
+      }\r
+\r
+      FvInfo->FvComponents[Index].Size = (UINTN) Value64;\r
+    } else {\r
+      printf ("WARNING: Could not read %s.\n", EFI_NV_EVENT_LOG_STRING);\r
+    }\r
+\r
+    Index++;\r
+    //\r
+    // Read component FV_FTW_WORKING\r
+    //\r
+    Status = FindToken (InfFile, COMPONENT_SECTION_STRING, EFI_NV_FTW_WORKING_STRING, 0, Value);\r
+\r
+    if (Status == EFI_SUCCESS) {\r
+      //\r
+      // Add the component\r
+      //\r
+      strcpy (FvInfo->FvComponents[Index].ComponentName, EFI_NV_FTW_WORKING_STRING);\r
+      Status = AsciiStringToUint64 (Value, FALSE, &Value64);\r
+      if (EFI_ERROR (Status)) {\r
+        printf ("ERROR: %s is not a valid integer.\n", EFI_NV_FTW_WORKING_STRING);\r
+        return EFI_ABORTED;\r
+      }\r
+\r
+      FvInfo->FvComponents[Index].Size = (UINTN) Value64;\r
+    } else {\r
+      printf ("WARNING: Could not read %s.\n", EFI_NV_FTW_WORKING_STRING);\r
+    }\r
+\r
+    Index++;\r
+    //\r
+    // Read component FV_FTW_SPARE\r
+    //\r
+    Status = FindToken (InfFile, COMPONENT_SECTION_STRING, EFI_NV_FTW_SPARE_STRING, 0, Value);\r
+\r
+    if (Status == EFI_SUCCESS) {\r
+      //\r
+      // Add the component\r
+      //\r
+      strcpy (FvInfo->FvComponents[Index].ComponentName, EFI_NV_FTW_SPARE_STRING);\r
+      Status = AsciiStringToUint64 (Value, FALSE, &Value64);\r
+      if (EFI_ERROR (Status)) {\r
+        printf ("ERROR: %s is not a valid integer.\n", EFI_NV_FTW_SPARE_STRING);\r
+        return EFI_ABORTED;\r
+      }\r
+\r
+      FvInfo->FvComponents[Index].Size = (UINTN) Value64;\r
+    } else {\r
+      printf ("WARNING: Could not read %s.\n", EFI_NV_FTW_SPARE_STRING);\r
+    }\r
+  }\r
+  //\r
+  // Compute size for easy access later\r
+  //\r
+  FvInfo->Size = 0;\r
+  for (Index = 0; FvInfo->FvBlocks[Index].NumBlocks; Index++) {\r
+    FvInfo->Size += FvInfo->FvBlocks[Index].NumBlocks * FvInfo->FvBlocks[Index].BlockLength;\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+VOID\r
+UpdateFfsFileState (\r
+  IN EFI_FFS_FILE_HEADER          *FfsFile,\r
+  IN EFI_FIRMWARE_VOLUME_HEADER   *FvHeader\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  This function changes the FFS file attributes based on the erase polarity\r
+  of the FV.\r
+\r
+Arguments:\r
+\r
+  FfsFile   File header.\r
+  FvHeader  FV header.\r
+\r
+Returns:\r
+\r
+  None\r
+\r
+--*/\r
+{\r
+  if (FvHeader->Attributes & EFI_FVB_ERASE_POLARITY) {\r
+    FfsFile->State = (UINT8)~(FfsFile->State);\r
+  }\r
+}\r
+\r
+EFI_STATUS\r
+ReadFfsAlignment (\r
+  IN EFI_FFS_FILE_HEADER    *FfsFile,\r
+  IN OUT UINT32             *Alignment\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  This function determines the alignment of the FFS input file from the file\r
+  attributes.\r
+\r
+Arguments:\r
+\r
+  FfsFile       FFS file to parse\r
+  Alignment     The minimum required alignment of the FFS file, in bytes\r
+\r
+Returns:\r
+\r
+  EFI_SUCCESS              The function completed successfully.\r
+  EFI_INVALID_PARAMETER    One of the input parameters was invalid.\r
+  EFI_ABORTED              An error occurred.\r
+\r
+--*/\r
+{\r
+  //\r
+  // Verify input parameters.\r
+  //\r
+  if (FfsFile == NULL || Alignment == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  switch ((FfsFile->Attributes >> 3) & 0x07) {\r
+\r
+  case 0:\r
+    //\r
+    // 1 byte alignment\r
+    //\r
+    *Alignment = (1 << 0);\r
+    break;\r
+\r
+  case 1:\r
+    //\r
+    // 16 byte alignment\r
+    //\r
+    *Alignment = (1 << 4);\r
+    break;\r
+\r
+  case 2:\r
+    //\r
+    // 128 byte alignment\r
+    //\r
+    *Alignment = (1 << 7);\r
+    break;\r
+\r
+  case 3:\r
+    //\r
+    // 512 byte alignment\r
+    //\r
+    *Alignment = (1 << 9);\r
+    break;\r
+\r
+  case 4:\r
+    //\r
+    // 1K byte alignment\r
+    //\r
+    *Alignment = (1 << 10);\r
+    break;\r
+\r
+  case 5:\r
+    //\r
+    // 4K byte alignment\r
+    //\r
+    *Alignment = (1 << 12);\r
+    break;\r
+\r
+  case 6:\r
+    //\r
+    // 32K byte alignment\r
+    //\r
+    *Alignment = (1 << 15);\r
+    break;\r
+\r
+  case 7:\r
+    //\r
+    // 64K byte alignment\r
+    //\r
+    *Alignment = (1 << 16);\r
+    break;\r
+\r
+  default:\r
+    Error (NULL, 0, 0, "nvalid file attribute calculated, this is most likely a utility error", NULL);\r
+    return EFI_ABORTED;\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+AddPadFile (\r
+  IN OUT MEMORY_FILE  *FvImage,\r
+  IN UINT32           DataAlignment\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  This function adds a pad file to the FV image if it required to align the\r
+  data of the next file.\r
+\r
+Arguments:\r
+\r
+  FvImage         The memory image of the FV to add it to.  The current offset\r
+                  must be valid.\r
+  DataAlignment   The data alignment of the next FFS file.\r
+\r
+Returns:\r
+\r
+  EFI_SUCCESS              The function completed successfully.\r
+  EFI_INVALID_PARAMETER    One of the input parameters was invalid.\r
+  EFI_OUT_OF_RESOURCES     Insufficient resources exist in the FV to complete\r
+                           the pad file add.\r
+\r
+--*/\r
+{\r
+  EFI_FFS_FILE_HEADER *PadFile;\r
+  UUID                PadFileGuid;\r
+  UINTN               PadFileSize;\r
+\r
+  //\r
+  // Verify input parameters.\r
+  //\r
+  if (FvImage == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+  //\r
+  // Basic assumption is we start from an 8 byte aligned address\r
+  // and our file header is a multiple of 8 bytes\r
+  //\r
+  assert ((UINTN) FvImage->CurrentFilePointer % 8 == 0);\r
+  assert (sizeof (EFI_FFS_FILE_HEADER) % 8 == 0);\r
+\r
+  //\r
+  // Check if a pad file is necessary\r
+  //\r
+  if (((UINTN) FvImage->CurrentFilePointer - (UINTN) FvImage->FileImage + sizeof (EFI_FFS_FILE_HEADER)) % DataAlignment == 0) {\r
+    return EFI_SUCCESS;\r
+  }\r
+  //\r
+  // Write pad file header\r
+  //\r
+  PadFile = (EFI_FFS_FILE_HEADER *) FvImage->CurrentFilePointer;\r
+\r
+  //\r
+  // Verify that we have enough space for the file header\r
+  //\r
+  if ((UINTN) (PadFile + sizeof (EFI_FFS_FILE_HEADER)) >= (UINTN) FvImage->Eof) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+\r
+  UuidCreate (&PadFileGuid);\r
+  memset (PadFile, 0, sizeof (EFI_FFS_FILE_HEADER));\r
+  memcpy (&PadFile->Name, &PadFileGuid, sizeof (EFI_GUID));\r
+  PadFile->Type       = EFI_FV_FILETYPE_FFS_PAD;\r
+  PadFile->Attributes = 0;\r
+\r
+  //\r
+  // Calculate the pad file size\r
+  //\r
+  //\r
+  // This is the earliest possible valid offset (current plus pad file header\r
+  // plus the next file header)\r
+  //\r
+  PadFileSize = (UINTN) FvImage->CurrentFilePointer - (UINTN) FvImage->FileImage + (sizeof (EFI_FFS_FILE_HEADER) * 2);\r
+\r
+  //\r
+  // Add whatever it takes to get to the next aligned address\r
+  //\r
+  while ((PadFileSize % DataAlignment) != 0) {\r
+    PadFileSize++;\r
+  }\r
+  //\r
+  // Subtract the next file header size\r
+  //\r
+  PadFileSize -= sizeof (EFI_FFS_FILE_HEADER);\r
+\r
+  //\r
+  // Subtract the starting offset to get size\r
+  //\r
+  PadFileSize -= (UINTN) FvImage->CurrentFilePointer - (UINTN) FvImage->FileImage;\r
+\r
+  //\r
+  // Write pad file size (calculated size minus next file header size)\r
+  //\r
+  PadFile->Size[0]  = (UINT8) (PadFileSize & 0xFF);\r
+  PadFile->Size[1]  = (UINT8) ((PadFileSize >> 8) & 0xFF);\r
+  PadFile->Size[2]  = (UINT8) ((PadFileSize >> 16) & 0xFF);\r
+\r
+  //\r
+  // Fill in checksums and state, they must be 0 for checksumming.\r
+  //\r
+  PadFile->IntegrityCheck.Checksum.Header = 0;\r
+  PadFile->IntegrityCheck.Checksum.File   = 0;\r
+  PadFile->State                          = 0;\r
+  PadFile->IntegrityCheck.Checksum.Header = CalculateChecksum8 ((UINT8 *) PadFile, sizeof (EFI_FFS_FILE_HEADER));\r
+  if (PadFile->Attributes & FFS_ATTRIB_CHECKSUM) {\r
+    PadFile->IntegrityCheck.Checksum.File = CalculateChecksum8 ((UINT8 *) PadFile, PadFileSize);\r
+  } else {\r
+    PadFile->IntegrityCheck.Checksum.File = FFS_FIXED_CHECKSUM;\r
+  }\r
+\r
+  PadFile->State = EFI_FILE_HEADER_CONSTRUCTION | EFI_FILE_HEADER_VALID | EFI_FILE_DATA_VALID;\r
+  UpdateFfsFileState (\r
+    (EFI_FFS_FILE_HEADER *) PadFile,\r
+    (EFI_FIRMWARE_VOLUME_HEADER *) FvImage->FileImage\r
+    );\r
+\r
+  //\r
+  // Verify that we have enough space (including the padding\r
+  //\r
+  if ((UINTN) (PadFile + sizeof (EFI_FFS_FILE_HEADER)) >= (UINTN) FvImage->Eof) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+  //\r
+  // Update the current FV pointer\r
+  //\r
+  FvImage->CurrentFilePointer += PadFileSize;\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+BOOLEAN\r
+IsVtfFile (\r
+  IN EFI_FFS_FILE_HEADER    *FileBuffer\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  This function checks the header to validate if it is a VTF file\r
+\r
+Arguments:\r
+\r
+  FileBuffer     Buffer in which content of a file has been read.\r
+\r
+Returns:\r
+\r
+  TRUE    If this is a VTF file\r
+  FALSE   If this is not a VTF file\r
+\r
+--*/\r
+{\r
+  EFI_GUID  VtfGuid = EFI_FFS_VOLUME_TOP_FILE_GUID;\r
+  if (!memcmp (&FileBuffer->Name, &VtfGuid, sizeof (EFI_GUID))) {\r
+    return TRUE;\r
+  } else {\r
+    return FALSE;\r
+  }\r
+}\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
+RebaseFfsFile (\r
+  IN OUT EFI_FFS_FILE_HEADER    *FfsFile,\r
+  IN EFI_PHYSICAL_ADDRESS       BaseAddress\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
+  FfsFile           A pointer to Ffs file image.\r
+  BaseAddress       The base address to use for rebasing the 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
+\r
+--*/\r
+{\r
+  EFI_STATUS                            Status;\r
+  EFI_PEI_PE_COFF_LOADER_IMAGE_CONTEXT  ImageContext;\r
+  UINTN                                 MemoryImagePointer;\r
+  UINTN                                 MemoryImagePointerAligned;\r
+\r
+  EFI_PHYSICAL_ADDRESS                  ImageAddress;\r
+  UINT64                                ImageSize;\r
+  EFI_PHYSICAL_ADDRESS                  EntryPoint;\r
+\r
+  UINT32                                Pe32FileSize;\r
+  UINT32                                NewPe32BaseAddress;\r
+\r
+  UINTN                                 Index;\r
+  EFI_FILE_SECTION_POINTER              CurrentPe32Section;\r
+  UINT8                                 FileGuidString[80];\r
+\r
+  //\r
+  // Verify input parameters\r
+  //\r
+  if (FfsFile == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+  //\r
+  // Convert the GUID to a string so we can at least report which file\r
+  // if we find an error.\r
+  //\r
+  PrintGuidToBuffer (&FfsFile->Name, FileGuidString, sizeof (FileGuidString), TRUE);\r
+\r
+  //\r
+  // Do some nominal checks on the file, then check for XIP.\r
+  //\r
+  Status = VerifyFfsFile (FfsFile);\r
+  if (EFI_ERROR (Status)) {\r
+    Error (NULL, 0, 0, "invalid FFS file", FileGuidString);\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  if (FfsFile->Type != EFI_FV_FILETYPE_SECURITY_CORE &&\r
+      FfsFile->Type != EFI_FV_FILETYPE_PEI_CORE &&\r
+      FfsFile->Type != EFI_FV_FILETYPE_PEIM\r
+      ) {\r
+    //\r
+    // File is not XIP, so don't rebase\r
+    //\r
+    return EFI_SUCCESS;\r
+  }\r
+  //\r
+  // Rebase each PE32 section\r
+  //\r
+  for (Index = 1;; Index++) {\r
+    Status = GetSectionByType (FfsFile, EFI_SECTION_PE32, Index, &CurrentPe32Section);\r
+    if (EFI_ERROR (Status)) {\r
+      break;\r
+    }\r
+    //\r
+    // Calculate the PE32 base address, the FFS file base plus the offset of the PE32 section\r
+    //\r
+    NewPe32BaseAddress = ((UINT32) BaseAddress) + ((UINTN) CurrentPe32Section.Pe32Section - (UINTN) FfsFile);\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  = (EFI_PEI_PE_COFF_LOADER_READ_FILE) FfsRebaseImageRead;\r
+\r
+    Status                  = mPeCoffLoader.GetImageInfo (&mPeCoffLoader, &ImageContext);\r
+\r
+    if (EFI_ERROR (Status)) {\r
+      Error (NULL, 0, 0, "GetImageInfo() failed", FileGuidString);\r
+      return Status;\r
+    }\r
+    //\r
+    // Allocate a buffer for the image to be loaded into.\r
+    //\r
+    Pe32FileSize              = GetLength (CurrentPe32Section.Pe32Section->CommonHeader.Size);\r
+    MemoryImagePointer        = (UINTN) (malloc (Pe32FileSize + 0x1000));\r
+    MemoryImagePointerAligned = (MemoryImagePointer + 0x0FFF) & (-1 << 12);\r
+    if (MemoryImagePointerAligned == 0) {\r
+      Error (NULL, 0, 0, "memory allocation failure", NULL);\r
+      return EFI_OUT_OF_RESOURCES;\r
+    }\r
+\r
+    //\r
+    // bugbug\r
+    //\r
+    ImageContext.ImageAddress = MemoryImagePointerAligned;\r
+    Status = mPeCoffLoader.LoadImage (&mPeCoffLoader, &ImageContext);\r
+    if (EFI_ERROR (Status)) {\r
+      Error (NULL, 0, 0, "LoadImage() failure", FileGuidString);\r
+      free ((VOID *) MemoryImagePointer);\r
+      return Status;\r
+    }\r
+\r
+    Status = mPeCoffLoader.RelocateImage (&mPeCoffLoader, &ImageContext);\r
+    if (EFI_ERROR (Status)) {\r
+      Error (NULL, 0, 0, "RelocateImage() failure", FileGuidString);\r
+      free ((VOID *) MemoryImagePointer);\r
+      return Status;\r
+    }\r
+\r
+    ImageAddress  = ImageContext.ImageAddress;\r
+    ImageSize     = ImageContext.ImageSize;\r
+    EntryPoint    = ImageContext.EntryPoint;\r
+\r
+    if (ImageSize > Pe32FileSize) {\r
+      Error (\r
+        NULL,\r
+        0,\r
+        0,\r
+        "rebased PE32 is larger than original PE32 image",\r
+        "0x%X > 0x%X on file %s",\r
+        ImageSize,\r
+        Pe32FileSize,\r
+        FileGuidString\r
+        );\r
+      free ((VOID *) MemoryImagePointer);\r
+      return EFI_ABORTED;\r
+    }\r
+\r
+    memcpy (CurrentPe32Section.Pe32Section, (VOID *) MemoryImagePointerAligned, Pe32FileSize);\r
+\r
+    free ((VOID *) MemoryImagePointer);\r
+  }\r
+  //\r
+  // the above for loop will always exit with EFI_NOT_FOUND if it completes\r
+  // normally.  If Index == 1 at exit, then no PE32 sections were found.  If it\r
+  // exits with any other error code, then something broke...\r
+  //\r
+  if (Status != EFI_NOT_FOUND) {\r
+    Error (NULL, 0, 0, "failed to parse PE32 section", FileGuidString);\r
+    return Status;\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+AddSymFile (\r
+  IN UINT64               BaseAddress,\r
+  IN EFI_FFS_FILE_HEADER  *FfsFile,\r
+  IN OUT MEMORY_FILE      *SymImage,\r
+  IN CHAR8                *SourceFileName\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  This function adds the SYM tokens in the source file to the destination file.\r
+  The SYM tokens are updated to reflect the base address.\r
+\r
+Arguments:\r
+\r
+  BaseAddress     The base address for the new SYM tokens.\r
+  FfsFile         Pointer to the beginning of the FFS file in question.\r
+  SymImage        The memory file to update with symbol information.\r
+  SourceFileName  The source file.\r
+\r
+Returns:\r
+\r
+  EFI_SUCCESS              The function completed successfully.\r
+  EFI_INVALID_PARAMETER    One of the input parameters was invalid.\r
+  EFI_ABORTED              An error occurred.\r
+\r
+--*/\r
+{\r
+  FILE                      *SourceFile;\r
+\r
+  CHAR8                     Buffer[_MAX_PATH];\r
+  CHAR8                     Type[_MAX_PATH];\r
+  CHAR8                     Address[_MAX_PATH];\r
+  CHAR8                     Section[_MAX_PATH];\r
+  CHAR8                     Token[_MAX_PATH];\r
+  CHAR8                     SymFileName[_MAX_PATH];\r
+  CHAR8                     CodeModuleName[_MAX_PATH];\r
+  CHAR8                     *Ptr;\r
+\r
+  UINT64                    TokenAddress;\r
+\r
+  EFI_STATUS                Status;\r
+  EFI_FILE_SECTION_POINTER  Pe32Section;\r
+  UINT32                    EntryPoint;\r
+  UINT32                    BaseOfCode;\r
+  UINT16                    MachineType;\r
+\r
+  //\r
+  // Verify input parameters.\r
+  //\r
+  if (BaseAddress == 0 || FfsFile == NULL || SymImage == NULL || SourceFileName == NULL) {\r
+    Error (NULL, 0, 0, "invalid parameter passed to AddSymFile()", NULL);\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+  //\r
+  // Check if we want to add this file\r
+  //\r
+  //\r
+  // Get the file name\r
+  //\r
+  strcpy (Buffer, SourceFileName);\r
+\r
+  //\r
+  // Copy the file name for the path of the sym file and truncate the name portion.\r
+  //\r
+  strcpy (SymFileName, Buffer);\r
+  Ptr = strrchr (SymFileName, '\\');\r
+  assert (Ptr);\r
+  Ptr[0] = 0;\r
+\r
+  //\r
+  // Find the file extension and make it lower case\r
+  //\r
+  Ptr = strrchr (SymFileName, '.');\r
+  if (Ptr != NULL) {\r
+    _strlwr (Ptr);\r
+  }\r
+  //\r
+  // Check if it is PEI file\r
+  //\r
+  if (strstr (Buffer, ".pei") != NULL) {\r
+    //\r
+    // Find the human readable portion\r
+    //\r
+    if (!strtok (Buffer, "-") ||\r
+        !strtok (NULL, "-") ||\r
+        !strtok (NULL, "-") ||\r
+        !strtok (NULL, "-") ||\r
+        !strtok (NULL, "-") ||\r
+        !strcpy (Buffer, strtok (NULL, "."))\r
+          ) {\r
+      Error (NULL, 0, 0, "failed to find human readable portion of the file name in AddSymFile()", NULL);\r
+      return EFI_ABORTED;\r
+    }\r
+    //\r
+    // Save code module name\r
+    //\r
+    strcpy (CodeModuleName, Buffer);\r
+\r
+    //\r
+    // Add the symbol file name and extension to the file path.\r
+    //\r
+    strcat (Buffer, ".sym");\r
+    strcat (SymFileName, "\\");\r
+    strcat (SymFileName, Buffer);\r
+  } else {\r
+    //\r
+    // Only handle PEIM files.\r
+    //\r
+    return EFI_SUCCESS;\r
+  }\r
+  //\r
+  // Find PE32 section\r
+  //\r
+  Status = GetSectionByType (FfsFile, EFI_SECTION_PE32, 1, &Pe32Section);\r
+\r
+  //\r
+  // BUGBUG: Assume if no PE32 section it is PIC and hardcode base address\r
+  //\r
+  if (Status == EFI_NOT_FOUND) {\r
+    Status = GetSectionByType (FfsFile, EFI_SECTION_TE, 1, &Pe32Section);\r
+  }\r
+\r
+  if (Status == EFI_SUCCESS) {\r
+    Status = GetPe32Info (\r
+               (VOID *) ((UINTN) Pe32Section.Pe32Section + sizeof (EFI_SECTION_PE32)),\r
+               &EntryPoint,\r
+               &BaseOfCode,\r
+               &MachineType\r
+               );\r
+  } else {\r
+    if (Status == EFI_NOT_FOUND) {\r
+      BaseOfCode = 0x60;\r
+      Status     = EFI_SUCCESS;\r
+    } else {\r
+      Error (NULL, 0, 0, "could not parse a PE32 section from the PEI file", NULL);\r
+      return Status;\r
+    }\r
+  }\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    Error (NULL, 0, 0, "GetPe32Info() could not get PE32 entry point for PEI file", NULL);\r
+    return Status;\r
+  }\r
+\r
+  //\r
+  // Open the source file\r
+  //\r
+  SourceFile = fopen (SymFileName, "r");\r
+  if (SourceFile == NULL) {\r
+    //\r
+    // SYM files are not required.\r
+    //\r
+    return EFI_SUCCESS;\r
+  }\r
+  //\r
+  // Read the first line\r
+  //\r
+  if (fgets (Buffer, _MAX_PATH, SourceFile) == NULL) {\r
+    Buffer[0] = 0;\r
+  }\r
+  //\r
+  // Make sure it matches the expected sym format\r
+  //\r
+  if (strcmp (Buffer, "TEXTSYM format | V1.0\n")) {\r
+    fclose (SourceFile);\r
+    Error (NULL, 0, 0, "AddSymFile() found unexpected sym format in input file", NULL);\r
+    return EFI_ABORTED;\r
+  }\r
+  //\r
+  // Read in the file\r
+  //\r
+  while (feof (SourceFile) == 0) {\r
+    //\r
+    // Read a line\r
+    //\r
+    if (fscanf (\r
+          SourceFile,\r
+          "%s | %s | %s | %s\n",\r
+          Type,\r
+          Address,\r
+          Section,\r
+          Token\r
+          ) == 4) {\r
+      //\r
+      // If the token starts with "??" ignore it\r
+      //\r
+      if (Token[0] == '?' && Token[1] == '?') {\r
+        continue;\r
+      }\r
+      //\r
+      // Get the token address\r
+      //\r
+      AsciiStringToUint64 (Address, TRUE, &TokenAddress);\r
+\r
+      //\r
+      // Add the base address\r
+      //\r
+      TokenAddress += BaseAddress;\r
+\r
+      //\r
+      // If PE32 or TE section then find the start of code.  For PIC it is hardcoded.\r
+      //\r
+      if (Pe32Section.Pe32Section) {\r
+        //\r
+        // Add the offset of the PE32 section\r
+        //\r
+        TokenAddress += (UINTN) Pe32Section.Pe32Section - (UINTN) FfsFile;\r
+\r
+        //\r
+        // Add the size of the PE32 section header\r
+        //\r
+        TokenAddress += sizeof (EFI_PE32_SECTION);\r
+      } else {\r
+        //\r
+        // BUGBUG: Don't know why this is 0x28 bytes.\r
+        //\r
+        TokenAddress += 0x28;\r
+      }\r
+      //\r
+      // Add the beginning of the code\r
+      //\r
+      TokenAddress += BaseOfCode;\r
+\r
+      sprintf (\r
+        Buffer,\r
+        "%s | %016I64X | %s | _%s%s\n",\r
+        Type,\r
+        TokenAddress,\r
+        Section,\r
+        CodeModuleName,\r
+        Token\r
+        );\r
+      memcpy (SymImage->CurrentFilePointer, Buffer, strlen (Buffer) + 1);\r
+      SymImage->CurrentFilePointer = (UINT8 *) (((UINTN) SymImage->CurrentFilePointer) + strlen (Buffer) + 1);\r
+    }\r
+  }\r
+\r
+  fclose (SourceFile);\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+AddFile (\r
+  IN OUT MEMORY_FILE          *FvImage,\r
+  IN FV_INFO                  *FvInfo,\r
+  IN UINTN                    Index,\r
+  IN OUT EFI_FFS_FILE_HEADER  **VtfFileImage,\r
+  IN OUT MEMORY_FILE          *SymImage\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  This function adds a file to the FV image.  The file will pad to the\r
+  appropriate alignment if required.\r
+\r
+Arguments:\r
+\r
+  FvImage       The memory image of the FV to add it to.  The current offset\r
+                must be valid.\r
+  FvInfo        Pointer to information about the FV.\r
+  Index         The file in the FvInfo file list to add.\r
+  VtfFileImage  A pointer to the VTF file within the FvImage.  If this is equal\r
+                to the end of the FvImage then no VTF previously found.\r
+  SymImage      The memory image of the Sym file to update if symbols are present.\r
+                The current offset must be valid.\r
+\r
+Returns:\r
+\r
+  EFI_SUCCESS              The function completed successfully.\r
+  EFI_INVALID_PARAMETER    One of the input parameters was invalid.\r
+  EFI_ABORTED              An error occurred.\r
+  EFI_OUT_OF_RESOURCES     Insufficient resources exist to complete the add.\r
+\r
+--*/\r
+{\r
+  FILE                  *NewFile;\r
+  UINTN                 FileSize;\r
+  UINT8                 *FileBuffer;\r
+  UINTN                 NumBytesRead;\r
+  UINT32                CurrentFileAlignment;\r
+  EFI_STATUS            Status;\r
+  EFI_PHYSICAL_ADDRESS  CurrentFileBaseAddress;\r
+  UINT8                 VtfHeaderChecksum;\r
+  UINT8                 VtfFileChecksum;\r
+  UINT8                 FileState;\r
+  UINT32                TailSize;\r
+#if (PI_SPECIFICATION_VERSION < 0x00010000)\r
+  EFI_FFS_FILE_TAIL     TailValue;\r
+#endif\r
+  //\r
+  // Verify input parameters.\r
+  //\r
+  if (FvImage == NULL || FvInfo == NULL || FvInfo->FvFiles[Index][0] == 0 || VtfFileImage == NULL || SymImage == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+  //\r
+  // Read the file to add\r
+  //\r
+  NewFile = fopen (FvInfo->FvFiles[Index], "rb");\r
+\r
+  if (NewFile == NULL) {\r
+    Error (NULL, 0, 0, FvInfo->FvFiles[Index], "failed to open file for reading");\r
+    return EFI_ABORTED;\r
+  }\r
+  //\r
+  // Get the file size\r
+  //\r
+  FileSize = _filelength (_fileno (NewFile));\r
+\r
+  //\r
+  // Read the file into a buffer\r
+  //\r
+  FileBuffer = malloc (FileSize);\r
+  if (FileBuffer == NULL) {\r
+    Error (NULL, 0, 0, "memory allocation failure", NULL);\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+\r
+  NumBytesRead = fread (FileBuffer, sizeof (UINT8), FileSize, NewFile);\r
+\r
+  //\r
+  // Done with the file, from this point on we will just use the buffer read.\r
+  //\r
+  fclose (NewFile);\r
+\r
+  //\r
+  // Verify read successful\r
+  //\r
+  if (NumBytesRead != sizeof (UINT8) * FileSize) {\r
+    free (FileBuffer);\r
+    Error (NULL, 0, 0, FvInfo->FvFiles[Index], "failed to read input file contents");\r
+    return EFI_ABORTED;\r
+  }\r
+  //\r
+  // Verify space exists to add the file\r
+  //\r
+  if (FileSize > (UINTN) ((UINTN) *VtfFileImage - (UINTN) FvImage->CurrentFilePointer)) {\r
+    Error (NULL, 0, 0, FvInfo->FvFiles[Index], "insufficient space remains to add the file");\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+  //\r
+  // Update the file state based on polarity of the FV.\r
+  //\r
+  UpdateFfsFileState (\r
+    (EFI_FFS_FILE_HEADER *) FileBuffer,\r
+    (EFI_FIRMWARE_VOLUME_HEADER *) FvImage->FileImage\r
+    );\r
+\r
+  //\r
+  // If we have a VTF file, add it at the top.\r
+  //\r
+  if (IsVtfFile ((EFI_FFS_FILE_HEADER *) FileBuffer)) {\r
+    if ((UINTN) *VtfFileImage == (UINTN) FvImage->Eof) {\r
+      //\r
+      // No previous VTF, add this one.\r
+      //\r
+      *VtfFileImage = (EFI_FFS_FILE_HEADER *) (UINTN) ((UINTN) FvImage->FileImage + FvInfo->Size - FileSize);\r
+      //\r
+      // Sanity check. The file MUST align appropriately\r
+      //\r
+      if ((((UINTN) *VtfFileImage) & 0x07) != 0) {\r
+        Error (NULL, 0, 0, "VTF file does not align on 8-byte boundary", NULL);\r
+      }\r
+      //\r
+      // copy VTF File Header\r
+      //\r
+      memcpy (*VtfFileImage, FileBuffer, sizeof (EFI_FFS_FILE_HEADER));\r
+\r
+      //\r
+      // Copy VTF body\r
+      //\r
+      memcpy (\r
+        (UINT8 *) *VtfFileImage + sizeof (EFI_FFS_FILE_HEADER),\r
+        FileBuffer + sizeof (EFI_FFS_FILE_HEADER),\r
+        FileSize - sizeof (EFI_FFS_FILE_HEADER)\r
+        );\r
+\r
+      //\r
+      // re-calculate the VTF File Header\r
+      //\r
+      FileState = (*VtfFileImage)->State;\r
+      (*VtfFileImage)->State = 0;\r
+      *(UINT32 *) ((*VtfFileImage)->Size) = FileSize;\r
+      (*VtfFileImage)->IntegrityCheck.Checksum.Header = 0;\r
+      (*VtfFileImage)->IntegrityCheck.Checksum.File = 0;\r
+\r
+      VtfHeaderChecksum = CalculateChecksum8 ((UINT8 *) *VtfFileImage, sizeof (EFI_FFS_FILE_HEADER));\r
+      (*VtfFileImage)->IntegrityCheck.Checksum.Header = VtfHeaderChecksum;\r
+      //\r
+      // Determine if it has a tail\r
+      //\r
+      if ((*VtfFileImage)->Attributes & FFS_ATTRIB_TAIL_PRESENT) {\r
+        TailSize = sizeof (EFI_FFS_FILE_TAIL);\r
+      } else {\r
+        TailSize = 0;\r
+      }\r
+\r
+      if ((*VtfFileImage)->Attributes & FFS_ATTRIB_CHECKSUM) {\r
+        VtfFileChecksum = CalculateChecksum8 ((UINT8 *) *VtfFileImage, FileSize - TailSize);\r
+        (*VtfFileImage)->IntegrityCheck.Checksum.File = VtfFileChecksum;\r
+      } else {\r
+        (*VtfFileImage)->IntegrityCheck.Checksum.File = FFS_FIXED_CHECKSUM;\r
+      }\r
+    #if (PI_SPECIFICATION_VERSION < 0x00010000)\r
+      //\r
+      // If it has a file tail, update it\r
+      //\r
+      if ((*VtfFileImage)->Attributes & FFS_ATTRIB_TAIL_PRESENT) {\r
+        TailValue = (EFI_FFS_FILE_TAIL) (~((*VtfFileImage)->IntegrityCheck.TailReference));\r
+        *(EFI_FFS_FILE_TAIL *) (((UINTN) (*VtfFileImage) + GetLength ((*VtfFileImage)->Size) - sizeof (EFI_FFS_FILE_TAIL))) = TailValue;\r
+      }\r
+    #endif  \r
+      (*VtfFileImage)->State = FileState;\r
+      free (FileBuffer);\r
+      return EFI_SUCCESS;\r
+    } else {\r
+      //\r
+      // Already found a VTF file.\r
+      //\r
+      Error (NULL, 0, 0, "multiple VTF files are illegal in a single FV", NULL);\r
+      free (FileBuffer);\r
+      return EFI_ABORTED;\r
+    }\r
+  }\r
+  //\r
+  // Check if alignment is required\r
+  //\r
+  Status = ReadFfsAlignment ((EFI_FFS_FILE_HEADER *) FileBuffer, &CurrentFileAlignment);\r
+  if (EFI_ERROR (Status)) {\r
+    printf ("ERROR: Could not determine alignment of file %s.\n", FvInfo->FvFiles[Index]);\r
+    free (FileBuffer);\r
+    return EFI_ABORTED;\r
+  }\r
+  //\r
+  // Add pad file if necessary\r
+  //\r
+  Status = AddPadFile (FvImage, CurrentFileAlignment);\r
+  if (EFI_ERROR (Status)) {\r
+    printf ("ERROR: Could not align the file data properly.\n");\r
+    free (FileBuffer);\r
+    return EFI_ABORTED;\r
+  }\r
+  //\r
+  // Add file\r
+  //\r
+  if ((FvImage->CurrentFilePointer + FileSize) < FvImage->Eof) {\r
+    //\r
+    // Copy the file\r
+    //\r
+    memcpy (FvImage->CurrentFilePointer, FileBuffer, FileSize);\r
+\r
+    //\r
+    // If the file is XIP, rebase\r
+    //\r
+    CurrentFileBaseAddress = FvInfo->BaseAddress + ((UINTN) FvImage->CurrentFilePointer - (UINTN) FvImage->FileImage);\r
+    //\r
+    //    Status = RebaseFfsFile ((EFI_FFS_FILE_HEADER*) FvImage->CurrentFilePointer, CurrentFileBaseAddress);\r
+    //    if (EFI_ERROR(Status)) {\r
+    //      printf ("ERROR: Could not rebase the file %s.\n", FvInfo->FvFiles[Index]);\r
+    //      return EFI_ABORTED;\r
+    //    }\r
+    //\r
+    // Update Symbol file\r
+    //\r
+    Status = AddSymFile (\r
+              CurrentFileBaseAddress,\r
+              (EFI_FFS_FILE_HEADER *) FvImage->CurrentFilePointer,\r
+              SymImage,\r
+              FvInfo->FvFiles[Index]\r
+              );\r
+    assert (!EFI_ERROR (Status));\r
+\r
+    //\r
+    // Update the current pointer in the FV image\r
+    //\r
+    FvImage->CurrentFilePointer += FileSize;\r
+  } else {\r
+    printf ("ERROR: The firmware volume is out of space, could not add file %s.\n", FvInfo->FvFiles[Index]);\r
+    return EFI_ABORTED;\r
+  }\r
+  //\r
+  // Make next file start at QWord Boundry\r
+  //\r
+  while (((UINTN) FvImage->CurrentFilePointer & 0x07) != 0) {\r
+    FvImage->CurrentFilePointer++;\r
+  }\r
+  //\r
+  // Free allocated memory.\r
+  //\r
+  free (FileBuffer);\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+AddVariableBlock (\r
+  IN UINT8                    *FvImage,\r
+  IN UINTN                    Size,\r
+  IN FV_INFO                  *FvInfo\r
+  )\r
+{\r
+  EFI_FIRMWARE_VOLUME_HEADER  *FvHeader;\r
+  VARIABLE_STORE_HEADER       *VarStoreHeader;\r
+  //\r
+  // Variable block should exclude FvHeader. Since the length of\r
+  // FvHeader depends on the block map, which is variable length,\r
+  // we could only decide the actual variable block length here.\r
+  //\r
+  FvHeader                  = (EFI_FIRMWARE_VOLUME_HEADER *) FvImage;\r
+  FvImage                   = FvImage + FvHeader->HeaderLength;\r
+\r
+  VarStoreHeader            = (VARIABLE_STORE_HEADER *) FvImage;\r
+\r
+  VarStoreHeader->Signature = VARIABLE_STORE_SIGNATURE;\r
+  VarStoreHeader->Size      = Size - FvHeader->HeaderLength;\r
+  VarStoreHeader->Format    = VARIABLE_STORE_FORMATTED;\r
+  VarStoreHeader->State     = VARIABLE_STORE_HEALTHY;\r
+  VarStoreHeader->Reserved  = 0;\r
+  VarStoreHeader->Reserved1 = 0;\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+AddEventLogBlock (\r
+  IN UINT8                    *FvImage,\r
+  IN UINTN                    Size,\r
+  IN FV_INFO                  *FvInfo\r
+  )\r
+{\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+AddFTWWorkingBlock (\r
+  IN UINT8                    *FvImage,\r
+  IN UINTN                    Size,\r
+  IN FV_INFO                  *FvInfo\r
+  )\r
+{\r
+  EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER *FTWHeader;\r
+  UINT32                                  Crc32;\r
+\r
+  Crc32     = 0;\r
+  FTWHeader = (EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER *) FvImage;\r
+  memcpy (&FTWHeader->Signature, &(FvInfo->FvGuid), sizeof (EFI_GUID));\r
+  FTWHeader->WriteQueueSize = Size - sizeof (EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER);\r
+  CalculateCrc32 (FvImage, sizeof (EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER), &Crc32);\r
+  FTWHeader->Crc = Crc32;\r
+  if (FvInfo->FvAttributes & EFI_FVB_ERASE_POLARITY) {\r
+    FTWHeader->WorkingBlockValid    = 0;\r
+    FTWHeader->WorkingBlockInvalid  = 1;\r
+  } else {\r
+    FTWHeader->WorkingBlockValid    = 1;\r
+    FTWHeader->WorkingBlockInvalid  = 0;\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+AddFTWSpareBlock (\r
+  IN UINT8                    *FvImage,\r
+  IN UINTN                    Size,\r
+  IN FV_INFO                  *FvInfo\r
+  )\r
+{\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+GenNonFFSFv (\r
+  IN UINT8                    *FvImage,\r
+  IN FV_INFO                  *FvInfo\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  This function generate the non FFS FV image, such as the working block\r
+  and spare block. How each component of the FV is built is component\r
+  specific.\r
+\r
+Arguments:\r
+\r
+  FvImage       The memory image of the FV to add it to.  The current offset\r
+                must be valid.\r
+  FvInfo        Pointer to information about the FV.\r
+\r
+Returns:\r
+\r
+  EFI_SUCCESS              The function completed successfully.\r
+  EFI_INVALID_PARAMETER    One of the input parameters was invalid.\r
+  EFI_ABORTED              An error occurred.\r
+  EFI_OUT_OF_RESOURCES     Insufficient resources exist to complete the add.\r
+\r
+--*/\r
+{\r
+  UINTN                       Index;\r
+  EFI_FIRMWARE_VOLUME_HEADER  *FvHeader;\r
+  UINT64                      TotalSize;\r
+\r
+  FvHeader  = (EFI_FIRMWARE_VOLUME_HEADER *) FvImage;\r
+  TotalSize = 0;\r
+\r
+  for (Index = 0; FvInfo->FvComponents[Index].Size != 0; Index++) {\r
+    if (_stricmp (FvInfo->FvComponents[Index].ComponentName, EFI_NV_VARIABLE_STRING) == 0) {\r
+      AddVariableBlock (FvImage, FvInfo->FvComponents[Index].Size, FvInfo);\r
+    } else if (_stricmp (FvInfo->FvComponents[Index].ComponentName, EFI_NV_EVENT_LOG_STRING) == 0) {\r
+      AddEventLogBlock (FvImage, FvInfo->FvComponents[Index].Size, FvInfo);\r
+    } else if (_stricmp (FvInfo->FvComponents[Index].ComponentName, EFI_NV_FTW_WORKING_STRING) == 0) {\r
+      AddFTWWorkingBlock (FvImage, FvInfo->FvComponents[Index].Size, FvInfo);\r
+    } else if (_stricmp (FvInfo->FvComponents[Index].ComponentName, EFI_NV_FTW_SPARE_STRING) == 0) {\r
+      AddFTWSpareBlock (FvImage, FvInfo->FvComponents[Index].Size, FvInfo);\r
+    } else {\r
+      printf ("Error. Unknown Non-FFS block %s \n", FvInfo->FvComponents[Index].ComponentName);\r
+      return EFI_ABORTED;\r
+    }\r
+\r
+    FvImage   = FvImage + FvInfo->FvComponents[Index].Size;\r
+    TotalSize = TotalSize + FvInfo->FvComponents[Index].Size;\r
+  }\r
+  //\r
+  // Index and TotalSize is zero mean there's no component, so this is an empty fv\r
+  //\r
+  if ((Index != 0 || TotalSize != 0) && TotalSize != FvInfo->Size) {\r
+    printf ("Error. Component size does not sum up to FV size.\n");\r
+    return EFI_ABORTED;\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+PadFvImage (\r
+  IN MEMORY_FILE          *FvImage,\r
+  IN EFI_FFS_FILE_HEADER  *VtfFileImage\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  This function places a pad file between the last file in the FV and the VTF\r
+  file if the VTF file exists.\r
+\r
+Arguments:\r
+\r
+  FvImage       Memory file for the FV memory image\r
+  VtfFileImage  The address of the VTF file.  If this is the end of the FV\r
+                image, no VTF exists and no pad file is needed.\r
+\r
+Returns:\r
+\r
+  EFI_SUCCESS             Completed successfully.\r
+  EFI_INVALID_PARAMETER   One of the input parameters was NULL.\r
+\r
+--*/\r
+{\r
+  EFI_FFS_FILE_HEADER *PadFile;\r
+  UINTN               FileSize;\r
+\r
+  //\r
+  // If there is no VTF or the VTF naturally follows the previous file without a\r
+  // pad file, then there's nothing to do\r
+  //\r
+  if ((UINTN) VtfFileImage == (UINTN) FvImage->Eof || (void *) FvImage->CurrentFilePointer == (void *) VtfFileImage) {\r
+    return EFI_SUCCESS;\r
+  }\r
+  //\r
+  // Pad file starts at beginning of free space\r
+  //\r
+  PadFile = (EFI_FFS_FILE_HEADER *) FvImage->CurrentFilePointer;\r
+\r
+  //\r
+  // write header\r
+  //\r
+  memset (PadFile, 0, sizeof (EFI_FFS_FILE_HEADER));\r
+  memcpy (&PadFile->Name, &DefaultFvPadFileNameGuid, sizeof (EFI_GUID));\r
+  PadFile->Type       = EFI_FV_FILETYPE_FFS_PAD;\r
+  PadFile->Attributes = 0;\r
+\r
+  //\r
+  // FileSize includes the EFI_FFS_FILE_HEADER\r
+  //\r
+  FileSize          = (UINTN) VtfFileImage - (UINTN) FvImage->CurrentFilePointer;\r
+  PadFile->Size[0]  = (UINT8) (FileSize & 0x000000FF);\r
+  PadFile->Size[1]  = (UINT8) ((FileSize & 0x0000FF00) >> 8);\r
+  PadFile->Size[2]  = (UINT8) ((FileSize & 0x00FF0000) >> 16);\r
+\r
+  //\r
+  // Fill in checksums and state, must be zero during checksum calculation.\r
+  //\r
+  PadFile->IntegrityCheck.Checksum.Header = 0;\r
+  PadFile->IntegrityCheck.Checksum.File   = 0;\r
+  PadFile->State                          = 0;\r
+  PadFile->IntegrityCheck.Checksum.Header = CalculateChecksum8 ((UINT8 *) PadFile, sizeof (EFI_FFS_FILE_HEADER));\r
+  if (PadFile->Attributes & FFS_ATTRIB_CHECKSUM) {\r
+    PadFile->IntegrityCheck.Checksum.File = CalculateChecksum8 ((UINT8 *) PadFile, FileSize);\r
+  } else {\r
+    PadFile->IntegrityCheck.Checksum.File = FFS_FIXED_CHECKSUM;\r
+  }\r
+\r
+  PadFile->State = EFI_FILE_HEADER_CONSTRUCTION | EFI_FILE_HEADER_VALID | EFI_FILE_DATA_VALID;\r
+\r
+  UpdateFfsFileState (\r
+    (EFI_FFS_FILE_HEADER *) PadFile,\r
+    (EFI_FIRMWARE_VOLUME_HEADER *) FvImage->FileImage\r
+    );\r
+  //\r
+  // Update the current FV pointer\r
+  //\r
+  FvImage->CurrentFilePointer = FvImage->Eof;\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+UpdateResetVector (\r
+  IN MEMORY_FILE            *FvImage,\r
+  IN FV_INFO                *FvInfo,\r
+  IN EFI_FFS_FILE_HEADER    *VtfFile\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  This parses the FV looking for the PEI core and then plugs the address into\r
+  the SALE_ENTRY point of the BSF/VTF for IPF and does BUGBUG TBD action to\r
+  complete an IA32 Bootstrap FV.\r
+\r
+Arguments:\r
+\r
+  FvImage       Memory file for the FV memory image\r
+  FvInfo        Information read from INF file.\r
+  VtfFile       Pointer to the VTF file in the FV image.\r
+\r
+Returns:\r
+\r
+  EFI_SUCCESS             Function Completed successfully.\r
+  EFI_ABORTED             Error encountered.\r
+  EFI_INVALID_PARAMETER   A required parameter was NULL.\r
+  EFI_NOT_FOUND           PEI Core file not found.\r
+\r
+--*/\r
+{\r
+  EFI_FFS_FILE_HEADER       *PeiCoreFile;\r
+  EFI_FFS_FILE_HEADER       *SecCoreFile;\r
+  EFI_STATUS                Status;\r
+  EFI_FILE_SECTION_POINTER  Pe32Section;\r
+  UINT32                    EntryPoint;\r
+  UINT32                    BaseOfCode;\r
+  UINT16                    MachineType;\r
+  EFI_PHYSICAL_ADDRESS      PeiCorePhysicalAddress;\r
+  EFI_PHYSICAL_ADDRESS      SecCorePhysicalAddress;\r
+  EFI_PHYSICAL_ADDRESS      *SecCoreEntryAddressPtr;\r
+  UINT32                    *Ia32ResetAddressPtr;\r
+  UINT8                     *BytePointer;\r
+  UINT8                     *BytePointer2;\r
+  UINT16                    *WordPointer;\r
+  UINT16                    CheckSum;\r
+  UINTN                     Index;\r
+  EFI_FFS_FILE_STATE        SavedState;\r
+  UINT32                    TailSize;\r
+  UINT64                    FitAddress;\r
+  FIT_TABLE                 *FitTablePtr;\r
+#if (PI_SPECIFICATION_VERSION < 0x00010000)\r
+  EFI_FFS_FILE_TAIL         TailValue;\r
+#endif\r
+  //\r
+  // Verify input parameters\r
+  //\r
+  if (FvImage == NULL || FvInfo == NULL || VtfFile == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+  //\r
+  // Initialize FV library\r
+  //\r
+  InitializeFvLib (FvImage->FileImage, (UINTN) FvImage->Eof - (UINTN) FvImage->FileImage);\r
+\r
+  //\r
+  // Verify VTF file\r
+  //\r
+  Status = VerifyFfsFile (VtfFile);\r
+  if (EFI_ERROR (Status)) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+  //\r
+  // Find the PEI Core\r
+  //\r
+  Status = GetFileByType (EFI_FV_FILETYPE_PEI_CORE, 1, &PeiCoreFile);\r
+  if (EFI_ERROR (Status) || PeiCoreFile == NULL) {\r
+    Error (NULL, 0, 0, "could not find the PEI core in the FV", NULL);\r
+    return EFI_ABORTED;\r
+  }\r
+  //\r
+  // PEI Core found, now find PE32 or TE section\r
+  //\r
+  Status = GetSectionByType (PeiCoreFile, EFI_SECTION_PE32, 1, &Pe32Section);\r
+  if (Status == EFI_NOT_FOUND) {\r
+    Status = GetSectionByType (PeiCoreFile, EFI_SECTION_TE, 1, &Pe32Section);\r
+  }\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    Error (NULL, 0, 0, "could not find PE32 or TE section in PEI core file", NULL);\r
+    return EFI_ABORTED;\r
+  }\r
+\r
+  Status = GetPe32Info (\r
+            (VOID *) ((UINTN) Pe32Section.Pe32Section + sizeof (EFI_SECTION_PE32)),\r
+            &EntryPoint,\r
+            &BaseOfCode,\r
+            &MachineType\r
+            );\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    Error (NULL, 0, 0, "could not get PE32 entry point for PEI core", NULL);\r
+    return EFI_ABORTED;\r
+  }\r
+  //\r
+  // Physical address is FV base + offset of PE32 + offset of the entry point\r
+  //\r
+  PeiCorePhysicalAddress = FvInfo->BaseAddress;\r
+  PeiCorePhysicalAddress += (UINTN) Pe32Section.Pe32Section + sizeof (EFI_SECTION_PE32) - (UINTN) FvImage->FileImage;\r
+  PeiCorePhysicalAddress += EntryPoint;\r
+\r
+  if (MachineType == EFI_IMAGE_MACHINE_IA64) {\r
+    //\r
+    // Update PEI_CORE address\r
+    //\r
+    //\r
+    // Set the uncached attribute bit in the physical address\r
+    //\r
+    PeiCorePhysicalAddress |= 0x8000000000000000;\r
+\r
+    //\r
+    // Check if address is aligned on a 16 byte boundary\r
+    //\r
+    if (PeiCorePhysicalAddress & 0xF) {\r
+      printf (\r
+        "ERROR: PEI_CORE entry point is not aligned on a 16 byte boundary, address specified is %Xh.\n",\r
+        PeiCorePhysicalAddress\r
+        );\r
+      return EFI_ABORTED;\r
+    }\r
+    //\r
+    // First Get the FIT table address\r
+    //\r
+    FitAddress  = (*(UINT64 *) (FvImage->Eof - IPF_FIT_ADDRESS_OFFSET)) & 0xFFFFFFFF;\r
+\r
+    FitTablePtr = (FIT_TABLE *) (FvImage->FileImage + (FitAddress - FvInfo->BaseAddress));\r
+\r
+    Status      = UpdatePeiCoreEntryInFit (FitTablePtr, PeiCorePhysicalAddress);\r
+\r
+    if (!EFI_ERROR (Status)) {\r
+      UpdateFitCheckSum (FitTablePtr);\r
+    }\r
+    //\r
+    // Find the Sec Core\r
+    //\r
+    Status = GetFileByType (EFI_FV_FILETYPE_SECURITY_CORE, 1, &SecCoreFile);\r
+    if (EFI_ERROR (Status) || SecCoreFile == NULL) {\r
+      Error (NULL, 0, 0, "could not find the Sec core in the FV", NULL);\r
+      return EFI_ABORTED;\r
+    }\r
+    //\r
+    // Sec Core found, now find PE32 section\r
+    //\r
+    Status = GetSectionByType (SecCoreFile, EFI_SECTION_PE32, 1, &Pe32Section);\r
+    if (EFI_ERROR (Status)) {\r
+      Error (NULL, 0, 0, "could not find PE32 section in SEC core file", NULL);\r
+      return EFI_ABORTED;\r
+    }\r
+\r
+    Status = GetPe32Info (\r
+              (VOID *) ((UINTN) Pe32Section.Pe32Section + sizeof (EFI_SECTION_PE32)),\r
+              &EntryPoint,\r
+              &BaseOfCode,\r
+              &MachineType\r
+              );\r
+    if (EFI_ERROR (Status)) {\r
+      Error (NULL, 0, 0, "could not get PE32 entry point for SEC core", NULL);\r
+      return EFI_ABORTED;\r
+    }\r
+    //\r
+    // Physical address is FV base + offset of PE32 + offset of the entry point\r
+    //\r
+    SecCorePhysicalAddress = FvInfo->BaseAddress;\r
+    SecCorePhysicalAddress += (UINTN) Pe32Section.Pe32Section + sizeof (EFI_SECTION_PE32) - (UINTN) FvImage->FileImage;\r
+    SecCorePhysicalAddress += EntryPoint;\r
+\r
+    //\r
+    // Update SEC_CORE address\r
+    //\r
+    //\r
+    // Set the uncached attribute bit in the physical address\r
+    //\r
+    SecCorePhysicalAddress |= 0x8000000000000000;\r
+\r
+    //\r
+    // Update the address\r
+    //\r
+    SecCoreEntryAddressPtr  = (EFI_PHYSICAL_ADDRESS *) ((UINTN) FvImage->Eof - IPF_SALE_ENTRY_ADDRESS_OFFSET);\r
+    *SecCoreEntryAddressPtr = SecCorePhysicalAddress;\r
+\r
+    //\r
+    // Check if address is aligned on a 16 byte boundary\r
+    //\r
+    if (SecCorePhysicalAddress & 0xF) {\r
+      printf (\r
+        "ERROR: SALE_ENTRY entry point is not aligned on a 16 byte boundary, address specified is %Xh.\n",\r
+        SecCorePhysicalAddress\r
+        );\r
+      return EFI_ABORTED;\r
+    }\r
+  } else if ((MachineType == EFI_IMAGE_MACHINE_IA32) || \r
+             (MachineType == EFI_IMAGE_MACHINE_X64)) {\r
+    //\r
+    // Get the location to update\r
+    //\r
+    Ia32ResetAddressPtr = (UINT32 *) ((UINTN) FvImage->Eof - IA32_PEI_CORE_ENTRY_OFFSET);\r
+\r
+    //\r
+    // Write lower 32 bits of physical address\r
+    //\r
+    *Ia32ResetAddressPtr = (UINT32) PeiCorePhysicalAddress;\r
+\r
+    //\r
+    // Update the BFV base address\r
+    //\r
+    Ia32ResetAddressPtr   = (UINT32 *) ((UINTN) FvImage->Eof - 4);\r
+    *Ia32ResetAddressPtr  = (UINT32) (FvInfo->BaseAddress);\r
+\r
+    CheckSum              = 0x0000;\r
+\r
+    //\r
+    // Update the Startup AP in the FVH header block ZeroVector region.\r
+    //\r
+    BytePointer   = (UINT8 *) ((UINTN) FvImage->FileImage);\r
+    BytePointer2  = (FvInfo->Size == 0x10000) ? m64kRecoveryStartupApDataArray : m128kRecoveryStartupApDataArray;\r
+    for (Index = 0; Index < SIZEOF_STARTUP_DATA_ARRAY; Index++) {\r
+      *BytePointer++ = *BytePointer2++;\r
+    }\r
+    //\r
+    // Calculate the checksum\r
+    //\r
+    WordPointer = (UINT16 *) ((UINTN) FvImage->FileImage);\r
+    for (Index = 0; Index < SIZEOF_STARTUP_DATA_ARRAY / 2; Index++) {\r
+      CheckSum = (UINT16) (CheckSum + ((UINT16) *WordPointer));\r
+      WordPointer++;\r
+    }\r
+    //\r
+    // Update the checksum field\r
+    //\r
+    BytePointer = (UINT8 *) ((UINTN) FvImage->FileImage);\r
+    BytePointer += (SIZEOF_STARTUP_DATA_ARRAY - 2);\r
+    WordPointer   = (UINT16 *) BytePointer;\r
+    *WordPointer  = (UINT16) (0x10000 - (UINT32) CheckSum);\r
+  } else {\r
+    Error (NULL, 0, 0, "invalid machine type in PEI core", "machine type=0x%X", (UINT32) MachineType);\r
+    return EFI_ABORTED;\r
+  }\r
+  //\r
+  // Determine if it has an FFS file tail.\r
+  //\r
+  if (VtfFile->Attributes & FFS_ATTRIB_TAIL_PRESENT) {\r
+    TailSize = sizeof (EFI_FFS_FILE_TAIL);\r
+  } else {\r
+    TailSize = 0;\r
+  }\r
+  //\r
+  // Now update file checksum\r
+  //\r
+  SavedState  = VtfFile->State;\r
+  VtfFile->IntegrityCheck.Checksum.File = 0;\r
+  VtfFile->State                        = 0;\r
+  if (VtfFile->Attributes & FFS_ATTRIB_CHECKSUM) {\r
+    VtfFile->IntegrityCheck.Checksum.File = CalculateChecksum8 (\r
+                                              (UINT8 *) VtfFile,\r
+                                              GetLength (VtfFile->Size) - TailSize\r
+                                              );\r
+  } else {\r
+    VtfFile->IntegrityCheck.Checksum.File = FFS_FIXED_CHECKSUM;\r
+  }\r
+\r
+  VtfFile->State = SavedState;\r
+\r
+#if (PI_SPECIFICATION_VERSION < 0x00010000)\r
+  //\r
+  // Update tail if present\r
+  //\r
+  if (VtfFile->Attributes & FFS_ATTRIB_TAIL_PRESENT) {\r
+    TailValue = (EFI_FFS_FILE_TAIL) (~(VtfFile->IntegrityCheck.TailReference));\r
+    *(EFI_FFS_FILE_TAIL *) (((UINTN) (VtfFile) + GetLength (VtfFile->Size) - sizeof (EFI_FFS_FILE_TAIL))) = TailValue;\r
+  }\r
+#endif\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+GetPe32Info (\r
+  IN UINT8                  *Pe32,\r
+  OUT UINT32                *EntryPoint,\r
+  OUT UINT32                *BaseOfCode,\r
+  OUT UINT16                *MachineType\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Retrieves the PE32 entry point offset and machine type from PE image or TE image.\r
+  See EfiImage.h for machine types.  The entry point offset is from the beginning\r
+  of the PE32 buffer passed in.\r
+\r
+Arguments:\r
+\r
+  Pe32          Beginning of the PE32.\r
+  EntryPoint    Offset from the beginning of the PE32 to the image entry point.\r
+  BaseOfCode    Base address of code.\r
+  MachineType   Magic number for the machine type.\r
+\r
+Returns:\r
+\r
+  EFI_SUCCESS             Function completed successfully.\r
+  EFI_ABORTED             Error encountered.\r
+  EFI_INVALID_PARAMETER   A required parameter was NULL.\r
+  EFI_UNSUPPORTED         The operation is unsupported.\r
+\r
+--*/\r
+{\r
+  EFI_IMAGE_DOS_HEADER  *DosHeader;\r
+  EFI_IMAGE_NT_HEADERS  *NtHeader;\r
+  EFI_TE_IMAGE_HEADER   *TeHeader;\r
+\r
+  //\r
+  // Verify input parameters\r
+  //\r
+  if (Pe32 == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  //\r
+  // First check whether it is one TE Image.\r
+  //\r
+  TeHeader = (EFI_TE_IMAGE_HEADER *) Pe32;\r
+  if (TeHeader->Signature == EFI_TE_IMAGE_HEADER_SIGNATURE) {\r
+    //\r
+    // By TeImage Header to get output\r
+    //\r
+    *EntryPoint  = TeHeader->AddressOfEntryPoint + sizeof (EFI_TE_IMAGE_HEADER) - TeHeader->StrippedSize;\r
+    *BaseOfCode  = TeHeader->BaseOfCode + sizeof (EFI_TE_IMAGE_HEADER) - TeHeader->StrippedSize;\r
+    *MachineType = TeHeader->Machine;\r
+  } else {\r
+    //\r
+    // Then check whether\r
+    // is the DOS header\r
+    //\r
+    DosHeader = (EFI_IMAGE_DOS_HEADER *) Pe32;\r
+\r
+    //\r
+    // Verify DOS header is expected\r
+    //\r
+    if (DosHeader->e_magic != EFI_IMAGE_DOS_SIGNATURE) {\r
+      printf ("ERROR: Unknown magic number in the DOS header, 0x%04X.\n", DosHeader->e_magic);\r
+      return EFI_UNSUPPORTED;\r
+    }\r
+    //\r
+    // Immediately following is the NT header.\r
+    //\r
+    NtHeader = (EFI_IMAGE_NT_HEADERS *) ((UINTN) Pe32 + DosHeader->e_lfanew);\r
+    \r
+    //\r
+    // Verify NT header is expected\r
+    //\r
+    if (NtHeader->Signature != EFI_IMAGE_NT_SIGNATURE) {\r
+      printf ("ERROR: Unrecognized image signature 0x%08X.\n", NtHeader->Signature);\r
+      return EFI_UNSUPPORTED;\r
+    }\r
+    //\r
+    // Get output\r
+    //\r
+    *EntryPoint   = NtHeader->OptionalHeader.AddressOfEntryPoint;\r
+    *BaseOfCode   = NtHeader->OptionalHeader.BaseOfCode;\r
+    *MachineType  = NtHeader->FileHeader.Machine;\r
+  }\r
+\r
+  //\r
+  // Verify machine type is supported\r
+  //\r
+  if (*MachineType != EFI_IMAGE_MACHINE_IA32 && \r
+      *MachineType != EFI_IMAGE_MACHINE_IA64 &&\r
+      *MachineType != EFI_IMAGE_MACHINE_X64) {\r
+    printf ("ERROR: Unrecognized machine type in the PE32 file.\n");\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+//\r
+// Exposed function implementations (prototypes are defined in GenFvImageLib.h)\r
+//\r
+EFI_STATUS\r
+GenerateFvImage (\r
+  IN CHAR8    *InfFileImage,\r
+  IN UINTN    InfFileSize,\r
+  OUT UINT8   **FvImage,\r
+  OUT UINTN   *FvImageSize,\r
+  OUT CHAR8   **FvFileName,\r
+  OUT UINT8   **SymImage,\r
+  OUT UINTN   *SymImageSize,\r
+  OUT CHAR8   **SymFileName\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  This is the main function which will be called from application.\r
+\r
+Arguments:\r
+\r
+  InfFileImage  Buffer containing the INF file contents.\r
+  InfFileSize   Size of the contents of the InfFileImage buffer.\r
+  FvImage       Pointer to the FV image created.\r
+  FvImageSize   Size of the FV image created and pointed to by FvImage.\r
+  FvFileName    Requested name for the FV file.\r
+  SymImage      Pointer to the Sym image created.\r
+  SymImageSize  Size of the Sym image created and pointed to by SymImage.\r
+  SymFileName   Requested name for the Sym file.\r
+\r
+Returns:\r
+\r
+  EFI_SUCCESS             Function completed successfully.\r
+  EFI_OUT_OF_RESOURCES    Could not allocate required resources.\r
+  EFI_ABORTED             Error encountered.\r
+  EFI_INVALID_PARAMETER   A required parameter was NULL.\r
+\r
+--*/\r
+{\r
+  EFI_STATUS                  Status;\r
+  MEMORY_FILE                 InfMemoryFile;\r
+  MEMORY_FILE                 FvImageMemoryFile;\r
+  MEMORY_FILE                 SymImageMemoryFile;\r
+  FV_INFO                     FvInfo;\r
+  UINTN                       Index;\r
+  EFI_FIRMWARE_VOLUME_HEADER  *FvHeader;\r
+  EFI_FFS_FILE_HEADER         *VtfFileImage;\r
+\r
+  //\r
+  // Check for invalid parameter\r
+  //\r
+  if (InfFileImage == NULL || FvImage == NULL || FvImageSize == NULL || FvFileName == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+  //\r
+  // Initialize file structures\r
+  //\r
+  InfMemoryFile.FileImage           = InfFileImage;\r
+  InfMemoryFile.CurrentFilePointer  = InfFileImage;\r
+  InfMemoryFile.Eof                 = InfFileImage + InfFileSize;\r
+\r
+  //\r
+  // Parse the FV inf file for header information\r
+  //\r
+  Status = ParseFvInf (&InfMemoryFile, &FvInfo);\r
+  if (EFI_ERROR (Status)) {\r
+    printf ("ERROR: Could not parse the input INF file.\n");\r
+    return EFI_ABORTED;\r
+  }\r
+  //\r
+  // Update the file name return values\r
+  //\r
+  strcpy (*FvFileName, FvInfo.FvName);\r
+  strcpy (*SymFileName, FvInfo.SymName);\r
+\r
+  //\r
+  // Calculate the FV size\r
+  //\r
+  *FvImageSize = FvInfo.Size;\r
+\r
+  //\r
+  // Allocate the FV\r
+  //\r
+  *FvImage = malloc (*FvImageSize);\r
+  if (*FvImage == NULL) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+  //\r
+  // Allocate space for symbol file storage\r
+  //\r
+  *SymImage = malloc (SYMBOL_FILE_SIZE);\r
+  if (*SymImage == NULL) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+  //\r
+  // Initialize the FV to the erase polarity\r
+  //\r
+  if (FvInfo.FvAttributes & EFI_FVB_ERASE_POLARITY) {\r
+    memset (*FvImage, -1, *FvImageSize);\r
+  } else {\r
+    memset (*FvImage, 0, *FvImageSize);\r
+  }\r
+  //\r
+  // Initialize FV header\r
+  //\r
+  FvHeader = (EFI_FIRMWARE_VOLUME_HEADER *) *FvImage;\r
+\r
+  //\r
+  // Initialize the zero vector to all zeros.\r
+  //\r
+  memset (FvHeader->ZeroVector, 0, 16);\r
+\r
+  //\r
+  // Copy the FFS GUID\r
+  //\r
+  memcpy (&FvHeader->FileSystemGuid, &FvInfo.FvGuid, sizeof (EFI_GUID));\r
+\r
+  FvHeader->FvLength    = *FvImageSize;\r
+  FvHeader->Signature   = EFI_FVH_SIGNATURE;\r
+  FvHeader->Attributes  = FvInfo.FvAttributes;\r
+#if (PI_SPECIFICATION_VERSION < 0x00010000)\r
+  FvHeader->Revision    = EFI_FVH_REVISION;\r
+  FvHeader->Reserved[0] = 0;\r
+  FvHeader->Reserved[1] = 0;\r
+  FvHeader->Reserved[2] = 0;\r
+#else\r
+  FvHeader->Revision    = EFI_FVH_PI_REVISION;\r
+  FvHeader->ExtHeaderOffset = 0;\r
+  FvHeader->Reserved[0] = 0;\r
+#endif\r
+  //\r
+  // Copy firmware block map\r
+  //\r
+  for (Index = 0; FvInfo.FvBlocks[Index].NumBlocks != 0; Index++) {\r
+    FvHeader->FvBlockMap[Index].NumBlocks   = FvInfo.FvBlocks[Index].NumBlocks;\r
+    FvHeader->FvBlockMap[Index].BlockLength = FvInfo.FvBlocks[Index].BlockLength;\r
+  }\r
+  //\r
+  // Add block map terminator\r
+  //\r
+  FvHeader->FvBlockMap[Index].NumBlocks   = 0;\r
+  FvHeader->FvBlockMap[Index].BlockLength = 0;\r
+\r
+  //\r
+  // Complete the header\r
+  //\r
+  FvHeader->HeaderLength  = (UINT16) (((UINTN) &(FvHeader->FvBlockMap[Index + 1])) - (UINTN) *FvImage);\r
+  FvHeader->Checksum      = 0;\r
+  FvHeader->Checksum      = CalculateChecksum16 ((UINT16 *) FvHeader, FvHeader->HeaderLength / sizeof (UINT16));\r
+\r
+  //\r
+  // If there is no FFS file, find and generate each components of the FV\r
+  //\r
+  if (FvInfo.FvFiles[0][0] == 0) {\r
+    Status = GenNonFFSFv (*FvImage, &FvInfo);\r
+    if (EFI_ERROR (Status)) {\r
+      printf ("ERROR: Could not generate NonFFS FV.\n");\r
+      free (*FvImage);\r
+      return EFI_ABORTED;\r
+    }\r
+\r
+    return EFI_SUCCESS;\r
+  }\r
+  //\r
+  // Initialize our "file" view of the buffer\r
+  //\r
+  FvImageMemoryFile.FileImage           = *FvImage;\r
+  FvImageMemoryFile.CurrentFilePointer  = *FvImage + FvHeader->HeaderLength;\r
+  FvImageMemoryFile.Eof                 = *FvImage +*FvImageSize;\r
+\r
+  //\r
+  // Initialize our "file" view of the symbol file.\r
+  //\r
+  SymImageMemoryFile.FileImage          = *SymImage;\r
+  SymImageMemoryFile.CurrentFilePointer = *SymImage;\r
+  SymImageMemoryFile.Eof                = *FvImage + SYMBOL_FILE_SIZE;\r
+\r
+  //\r
+  // Initialize the FV library.\r
+  //\r
+  InitializeFvLib (FvImageMemoryFile.FileImage, FvInfo.Size);\r
+\r
+  //\r
+  // Files start on 8 byte alignments, so move to the next 8 byte aligned\r
+  // address.  For now, just assert if it isn't.  Currently FV header is\r
+  // always a multiple of 8 bytes.\r
+  // BUGBUG: Handle this better\r
+  //\r
+  assert ((((UINTN) FvImageMemoryFile.CurrentFilePointer) % 8) == 0);\r
+\r
+  //\r
+  // Initialize the VTF file address.\r
+  //\r
+  VtfFileImage = (EFI_FFS_FILE_HEADER *) FvImageMemoryFile.Eof;\r
+\r
+  //\r
+  // Add files to FV\r
+  //\r
+  for (Index = 0; FvInfo.FvFiles[Index][0] != 0; Index++) {\r
+    //\r
+    // Add the file\r
+    //\r
+    Status = AddFile (&FvImageMemoryFile, &FvInfo, Index, &VtfFileImage, &SymImageMemoryFile);\r
+\r
+    //\r
+    // Exit if error detected while adding the file\r
+    //\r
+    if (EFI_ERROR (Status)) {\r
+      printf ("ERROR: Could not add file %s.\n", FvInfo.FvFiles[Index]);\r
+      free (*FvImage);\r
+      return EFI_ABORTED;\r
+    }\r
+  }\r
+  //\r
+  // If there is a VTF file, some special actions need to occur.\r
+  //\r
+  if ((UINTN) VtfFileImage != (UINTN) FvImageMemoryFile.Eof) {\r
+    //\r
+    // Pad from the end of the last file to the beginning of the VTF file.\r
+    //\r
+    Status = PadFvImage (&FvImageMemoryFile, VtfFileImage);\r
+    if (EFI_ERROR (Status)) {\r
+      printf ("ERROR: Could not create the pad file between the last file and the VTF file.\n");\r
+      free (*FvImage);\r
+      return EFI_ABORTED;\r
+    }\r
+    //\r
+    // Update reset vector (SALE_ENTRY for IPF)\r
+    // Now for IA32 and IA64 platform, the fv which has bsf file must have the \r
+    // EndAddress of 0xFFFFFFFF. Thus, only this type fv needs to update the   \r
+    // reset vector. If the PEI Core is found, the VTF file will probably get  \r
+    // corrupted by updating the entry point.                                  \r
+    //\r
+    if ((FvInfo.BaseAddress + FvInfo.Size) == FV_IMAGES_TOP_ADDRESS) {       \r
+      Status = UpdateResetVector (&FvImageMemoryFile, &FvInfo, VtfFileImage);\r
+      if (EFI_ERROR(Status)) {                                               \r
+        printf ("ERROR: Could not update the reset vector.\n");              \r
+        free (*FvImage);                                                     \r
+        return EFI_ABORTED;                                                  \r
+      }                                                                      \r
+    }\r
+  } \r
+  //\r
+  // Determine final Sym file size\r
+  //\r
+  *SymImageSize = SymImageMemoryFile.CurrentFilePointer - SymImageMemoryFile.FileImage;\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+UpdatePeiCoreEntryInFit (\r
+  IN FIT_TABLE     *FitTablePtr,\r
+  IN UINT64        PeiCorePhysicalAddress\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  This function is used to update the Pei Core address in FIT, this can be used by Sec core to pass control from\r
+  Sec to Pei Core\r
+\r
+Arguments:\r
+\r
+  FitTablePtr             - The pointer of FIT_TABLE.\r
+  PeiCorePhysicalAddress  - The address of Pei Core entry.\r
+\r
+Returns:\r
+\r
+  EFI_SUCCESS             - The PEI_CORE FIT entry was updated successfully.\r
+  EFI_NOT_FOUND           - Not found the PEI_CORE FIT entry.\r
+\r
+--*/\r
+{\r
+  FIT_TABLE *TmpFitPtr;\r
+  UINTN     Index;\r
+  UINTN     NumFitComponents;\r
+\r
+  TmpFitPtr         = FitTablePtr;\r
+  NumFitComponents  = TmpFitPtr->CompSize;\r
+\r
+  for (Index = 0; Index < NumFitComponents; Index++) {\r
+    if ((TmpFitPtr->CvAndType & FIT_TYPE_MASK) == COMP_TYPE_FIT_PEICORE) {\r
+      TmpFitPtr->CompAddress = PeiCorePhysicalAddress;\r
+      return EFI_SUCCESS;\r
+    }\r
+\r
+    TmpFitPtr++;\r
+  }\r
+\r
+  return EFI_NOT_FOUND;\r
+}\r
+\r
+VOID\r
+UpdateFitCheckSum (\r
+  IN FIT_TABLE   *FitTablePtr\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  This function is used to update the checksum for FIT.\r
+\r
+\r
+Arguments:\r
+\r
+  FitTablePtr             - The pointer of FIT_TABLE.\r
+\r
+Returns:\r
+\r
+  None.\r
+\r
+--*/\r
+{\r
+  if ((FitTablePtr->CvAndType & CHECKSUM_BIT_MASK) >> 7) {\r
+    FitTablePtr->CheckSum = 0;\r
+    FitTablePtr->CheckSum = CalculateChecksum8 ((UINT8 *) FitTablePtr, FitTablePtr->CompSize * 16);\r
+  }\r
+}\r