[edk2-devel] [edk2-platform patch 5/6] Silicon\Tools: Add a tool FitGen

Liming Gao liming.gao at intel.com
Wed Jun 26 02:03:23 UTC 2019


Shenglei:
  The patch is good to me. Reviewed-by: Liming Gao <liming.gao at intel.com>

Thanks
Liming
>-----Original Message-----
>From: devel at edk2.groups.io [mailto:devel at edk2.groups.io] On Behalf Of
>Zhang, Shenglei
>Sent: Friday, June 21, 2019 9:27 AM
>To: devel at edk2.groups.io
>Cc: Feng, Bob C <bob.c.feng at intel.com>; Gao, Liming <liming.gao at intel.com>
>Subject: [edk2-devel] [edk2-platform patch 5/6] Silicon\Tools: Add a tool
>FitGen
>
>The utility of this tool is part of build process for IA32/X64 FD.
>It generates FIT table.
>https://bugzilla.tianocore.org/show_bug.cgi?id=1849
>
>Cc: Bob Feng <bob.c.feng at intel.com>
>Cc: Liming Gao <liming.gao at intel.com>
>Signed-off-by: Shenglei Zhang <shenglei.zhang at intel.com>
>---
> Silicon/Intel/Tools/FitGen/FitGen.c    | 3137 ++++++++++++++++++++++++
> Silicon/Intel/Tools/FitGen/FitGen.h    |   48 +
> Silicon/Intel/Tools/FitGen/GNUmakefile |   16 +
> Silicon/Intel/Tools/FitGen/Makefile    |   17 +
> 4 files changed, 3218 insertions(+)
> create mode 100644 Silicon/Intel/Tools/FitGen/FitGen.c
> create mode 100644 Silicon/Intel/Tools/FitGen/FitGen.h
> create mode 100644 Silicon/Intel/Tools/FitGen/GNUmakefile
> create mode 100644 Silicon/Intel/Tools/FitGen/Makefile
>
>diff --git a/Silicon/Intel/Tools/FitGen/FitGen.c
>b/Silicon/Intel/Tools/FitGen/FitGen.c
>new file mode 100644
>index 0000000000..faf9880060
>--- /dev/null
>+++ b/Silicon/Intel/Tools/FitGen/FitGen.c
>@@ -0,0 +1,3137 @@
>+/**@file
>+This utility is part of build process for IA32/X64 FD.
>+It generates FIT table.
>+
>+Copyright (c) 2010-2019, Intel Corporation. All rights reserved.<BR>
>+SPDX-License-Identifier: BSD-2-Clause-Patent
>+
>+**/
>+
>+#include "FitGen.h"
>+
>+//
>+// FIT spec
>+//
>+#pragma pack (1)
>+typedef struct {
>+  UINT64     Address;
>+  UINT8      Size[3];
>+  UINT8      Rsvd;
>+  UINT16     Version;
>+  UINT8      Type:7;
>+  UINT8      C_V:1;
>+  UINT8      Checksum;
>+} FIRMWARE_INTERFACE_TABLE_ENTRY;
>+
>+//
>+// Struct for policy
>+//
>+typedef struct {
>+  UINT16     IndexPort;
>+  UINT16     DataPort;
>+  UINT8      Width;
>+  UINT8      Bit;
>+  UINT16     Index;
>+  UINT8      Size[3];
>+  UINT8      Rsvd;
>+  UINT16     Version; // == 0
>+  UINT8      Type:7;
>+  UINT8      C_V:1;
>+  UINT8      Checksum;
>+} FIRMWARE_INTERFACE_TABLE_ENTRY_PORT;
>+
>+#define FIT_ALIGNMENT          0x3F // 0xF is required previously, but if we
>need exclude FIT, we must set 64 bytes alignment.
>+#define BIOS_MODULE_ALIGNMENT  0x3F  // 64 bytes for AnC
>+#define MICROCODE_ALIGNMENT    0x7FF
>+
>+#define ACM_PKCS_1_5_RSA_SIGNATURE_SHA256_SIZE          256
>+#define ACM_PKCS_1_5_RSA_SIGNATURE_SHA384_SIZE          384
>+
>+#define ACM_HEADER_VERSION_3  (3 << 16)
>+#define ACM_MODULE_TYPE_CHIPSET_ACM                     2
>+#define ACM_MODULE_SUBTYPE_CAPABLE_OF_EXECUTE_AT_RESET  0x1
>+#define ACM_MODULE_SUBTYPE_ANC_MODULE                   0x2
>+#define ACM_MODULE_FLAG_PREPRODUCTION                   0x4000
>+#define ACM_MODULE_FLAG_DEBUG_SIGN                      0x8000
>+
>+
>+typedef struct {
>+  UINT16     ModuleType;
>+  UINT16     ModuleSubType;
>+  UINT32     HeaderLen;
>+  UINT32     HeaderVersion;
>+  UINT16     ChipsetID;
>+  UINT16     Flags;
>+  UINT32     ModuleVendor;
>+  UINT32     Date;
>+  UINT32     Size;
>+  UINT16     TxtSvn;
>+  UINT16     SeSvn;
>+  UINT32     CodeControl;
>+  UINT32     ErrorEntryPoint;
>+  UINT32     GDTLimit;
>+  UINT32     GDTBasePtr;
>+  UINT32     SegSel;
>+  UINT32     EntryPoint;
>+  UINT8      Rsvd2[64];
>+  UINT32     KeySize; // 64
>+  UINT32     ScratchSize; // 2 * KeySize + 15
>+//UINT8      RSAPubKey[64 * 4]; // KeySize * 4
>+//UINT32     RSAPubExp;
>+//UINT8      RSASig[256];
>+  // End of AC module header
>+//UINT8      Scratch[(64 * 2 + 15) * 4]; // ScratchSize * 4
>+  // User Area
>+//UINT8      UserArea[1];
>+} ACM_FORMAT;
>+
>+#define CHIPSET_ACM_INFORMATION_TABLE_VERSION_3  0x03
>+#define CHIPSET_ACM_INFORMATION_TABLE_VERSION_4  0x04
>+
>+#define CHIPSET_ACM_INFORMATION_TABLE_VERSION
>CHIPSET_ACM_INFORMATION_TABLE_VERSION_3
>+
>+#define CHIPSET_ACM_INFORMATION_TABLE_GUID_V03 \
>+  { 0x7FC03AAA, 0x18DB46A7, 0x8F69AC2E, 0x5A7F418D }
>+
>+#define CHIPSET_ACM_TYPE_BIOS   0
>+#define CHIPSET_ACM_TYPE_SINIT  1
>+
>+typedef struct {
>+  UINT32    Guid0;
>+  UINT32    Guid1;
>+  UINT32    Guid2;
>+  UINT32    Guid3;
>+} ACM_GUID;
>+
>+typedef struct {
>+  ACM_GUID   Guid;
>+  UINT8      ChipsetACMType;
>+  UINT8      Version;
>+  UINT16     Length;
>+  UINT32     ChipsetIDList;
>+  UINT32     OsSinitTableVer;
>+  UINT32     MinMleHeaderVer;
>+//#if (CHIPSET_ACM_INFORMATION_TABLE_VERSION >=
>CHIPSET_ACM_INFORMATION_TABLE_VERSION_3)
>+  UINT32     Capabilities;
>+  UINT8      AcmVersion;
>+  UINT8      AcmRevision[3];
>+//#if (CHIPSET_ACM_INFORMATION_TABLE_VERSION >=
>CHIPSET_ACM_INFORMATION_TABLE_VERSION_4)
>+  UINT32     ProcessorIDList;
>+//#endif
>+//#endif
>+} CHIPSET_ACM_INFORMATION_TABLE;
>+
>+#define ACM_CHIPSET_ID_REVISION_ID_MAKE  0x1
>+
>+typedef struct {
>+  UINT32     Flags;
>+  UINT16     VendorID;
>+  UINT16     DeviceID;
>+  UINT16     RevisionID;
>+  UINT8      Reserved[6];
>+} ACM_CHIPSET_ID;
>+
>+typedef struct {
>+  UINT32           Count;
>+  ACM_CHIPSET_ID   ChipsetID[1];
>+} CHIPSET_ID_LIST;
>+
>+typedef struct {
>+  UINT32     FMS;
>+  UINT32     FMSMask;
>+  UINT64     PlatformID;
>+  UINT64     PlatformMask;
>+} ACM_PROCESSOR_ID;
>+
>+typedef struct {
>+  UINT32           Count;
>+  ACM_PROCESSOR_ID ProcessorID[1];
>+} PROCESSOR_ID_LIST;
>+
>+#pragma pack ()
>+
>+
>+ACM_GUID mChipsetAcmInformationTableGuid03 =
>CHIPSET_ACM_INFORMATION_TABLE_GUID_V03;
>+
>+
>+//
>+// BIOS INFO data structure
>+// This is self contained data structure for BIOS info
>+//
>+#pragma pack (1)
>+#define BIOS_INFO_SIGNATURE  SIGNATURE_64 ('$', 'B', 'I', 'O', 'S', 'I', 'F', '$')
>+typedef struct {
>+  UINT64            Signature;
>+  UINT32            EntryCount;
>+  UINT32            Reserved;
>+//BIOS_INFO_STRUCT  Struct[EntryCount];
>+} BIOS_INFO_HEADER;
>+
>+//
>+// BIOS_INFO_STRUCT attributes
>+// bits[0:3] means general attributes
>+// bits[4:7] means type specific attributes
>+//
>+#define BIOS_INFO_STRUCT_ATTRIBUTE_GENERAL_EXCLUDE_FROM_FIT
>0x01
>+#define BIOS_INFO_STRUCT_ATTRIBUTE_MICROCODE_WHOLE_REGION
>0x10
>+#define BIOS_INFO_STRUCT_ATTRIBUTE_BIOS_POST_IBB             0x10
>+
>+typedef struct {
>+  //
>+  // FitTable entry type
>+  //
>+  UINT8    Type;
>+  //
>+  // BIOS_INFO_STRUCT attributes
>+  //
>+  UINT8    Attributes;
>+  //
>+  // FitTable entry version
>+  //
>+  UINT16   Version;
>+  //
>+  // FitTable entry real size
>+  //
>+  UINT32   Size;
>+  //
>+  // FitTable entry address
>+  //
>+  UINT64   Address;
>+} BIOS_INFO_STRUCT;
>+
>+#pragma pack ()
>+
>+#define MAX_BIOS_MODULE_ENTRY  0x20
>+#define MAX_MICROCODE_ENTRY    0x20
>+#define MAX_OPTIONAL_ENTRY     0x20
>+#define MAX_PORT_ENTRY         0x20
>+
>+#define DEFAULT_FIT_TABLE_POINTER_OFFSET  0x40
>+#define DEFAULT_FIT_ENTRY_VERSION         0x0100
>+
>+#define MEMORY_TO_FLASH(FileBuffer, FvBuffer, FvSize)  \
>+                 (UINTN)(0x100000000 - ((UINTN)(FvBuffer) + (UINTN)(FvSize) -
>(UINTN)(FileBuffer)))
>+#define FLASH_TO_MEMORY(Address, FvBuffer, FvSize)  \
>+                 (VOID *)(UINTN)((UINTN)(FvBuffer) + (UINTN)(FvSize) -
>(0x100000000 - (UINTN)(Address)))
>+
>+#define FIT_TABLE_TYPE_HEADER                 0
>+#define FIT_TABLE_TYPE_MICROCODE              1
>+#define FIT_TABLE_TYPE_STARTUP_ACM            2
>+#define FIT_TABLE_TYPE_BIOS_MODULE            7
>+#define FIT_TABLE_TYPE_TPM_POLICY             8
>+#define FIT_TABLE_TYPE_BIOS_POLICY            9
>+#define FIT_TABLE_TYPE_TXT_POLICY             10
>+#define FIT_TABLE_TYPE_KEY_MANIFEST           11
>+#define FIT_TABLE_TYPE_BOOT_POLICY_MANIFEST   12
>+#define FIT_TABLE_TYPE_BIOS_DATA_AREA         13
>+#define FIT_TABLE_TYPE_CSE_SECURE_BOOT        16
>+
>+typedef struct {
>+  UINT32  Type;
>+  UINT32  Address;
>+  UINT32  Size;
>+  UINT32  Version; // Used by OptionalModule and PortModule only
>+} FIT_TABLE_CONTEXT_ENTRY;
>+
>+typedef struct {
>+  BOOLEAN                    Clear;
>+  UINT32                     FitTablePointerOffset;
>+  UINT32                     FitTablePointerOffset2;
>+  UINT32                     FitEntryNumber;
>+  UINT32                     BiosModuleNumber;
>+  UINT32                     MicrocodeNumber;
>+  UINT32                     OptionalModuleNumber;
>+  UINT32                     PortModuleNumber;
>+  UINT32                     GlobalVersion;
>+  UINT32                     FitHeaderVersion;
>+  FIT_TABLE_CONTEXT_ENTRY    StartupAcm;
>+  UINT32                     StartupAcmVersion;
>+  FIT_TABLE_CONTEXT_ENTRY    BiosModule[MAX_BIOS_MODULE_ENTRY];
>+  UINT32                     BiosModuleVersion;
>+  FIT_TABLE_CONTEXT_ENTRY    Microcode[MAX_MICROCODE_ENTRY];
>+  BOOLEAN                    MicrocodeAlignment;
>+  UINT32                     MicrocodeVersion;
>+  FIT_TABLE_CONTEXT_ENTRY    OptionalModule[MAX_OPTIONAL_ENTRY];
>+  FIT_TABLE_CONTEXT_ENTRY    PortModule[MAX_PORT_ENTRY];
>+} FIT_TABLE_CONTEXT;
>+
>+FIT_TABLE_CONTEXT   gFitTableContext = {0};
>+
>+unsigned int
>+xtoi (
>+  char  *str
>+  );
>+
>+VOID
>+PrintUtilityInfo (
>+  VOID
>+  )
>+/*++
>+
>+Routine Description:
>+
>+  Displays the standard utility information to STDOUT
>+
>+Arguments:
>+
>+  None
>+
>+Returns:
>+
>+  None
>+
>+--*/
>+{
>+  printf (
>+    "%s - Tiano IA32/X64 FIT table generation Utility."" Version %i.%i\n\n",
>+    UTILITY_NAME,
>+    UTILITY_MAJOR_VERSION,
>+    UTILITY_MINOR_VERSION
>+    );
>+}
>+
>+VOID
>+PrintUsage (
>+  VOID
>+  )
>+/*++
>+
>+Routine Description:
>+
>+  Displays the utility usage syntax to STDOUT
>+
>+Arguments:
>+
>+  None
>+
>+Returns:
>+
>+  None
>+
>+--*/
>+{
>+  printf ("Usage (generate): %s [-D] InputFvRecoveryFile
>OutputFvRecoveryFile\n"
>+          "\t[-V <FitEntryDefaultVersion>]\n"
>+          "\t[-F <FitTablePointerOffset>] [-F <FitTablePointerOffset>] [-V
><FitHeaderVersion>]\n"
>+          "\t[-NA]\n"
>+          "\t[-CLEAR]\n"
>+          "\t[-I <BiosInfoGuid>]\n"
>+          "\t[-S <StartupAcmAddress StartupAcmSize>|<StartupAcmGuid>] [-V
><StartupAcmVersion>]\n"
>+          "\t[-B <BiosModuleAddress BiosModuleSize>] [-B ...] [-V
><BiosModuleVersion>]\n"
>+          "\t[-M <MicrocodeAddress MicrocodeSize>] [-M ...]|[-U <MicrocodeFv
>MicrocodeBase>|<MicrocodeRegionOffset
>MicrocodeRegionSize>|<MicrocodeGuid>] [-V <MicrocodeVersion>]\n"
>+          "\t[-O RecordType <RecordDataAddress RecordDataSize>|<RESERVE
>RecordDataSize>|<RecordDataGuid>|<RecordBinFile> [-V <RecordVersion>]]
>[-O ... [-V ...]]\n"
>+          "\t[-P RecordType <IndexPort DataPort Width Bit Index> [-V
><RecordVersion>]] [-P ... [-V ...]]\n"
>+          , UTILITY_NAME);
>+  printf ("  Where:\n");
>+  printf ("\t-D                     - It is FD file instead of FV file. (The tool will search FV
>file)\n");
>+  printf ("\tInputFvRecoveryFile    - Name of the input FvRecovery.fv file.\n");
>+  printf ("\tOutputFvRecoveryFile   - Name of the output FvRecovery.fv
>file.\n");
>+  printf ("\tFitTablePointerOffset  - FIT table pointer offset. 0x%x as default.
>0x18 for current soon to be obsoleted CPUs. User can set both.\n",
>DEFAULT_FIT_TABLE_POINTER_OFFSET);
>+  printf ("\tBiosInfoGuid           - Guid of BiosInfo Module. If this module exists,
>StartupAcm/Bios/Microcode can be optional.\n");
>+  printf ("\tStartupAcmAddress      - Address of StartupAcm.\n");
>+  printf ("\tStartupAcmSize         - Size of StartupAcm.\n");
>+  printf ("\tStartupAcmGuid         - Guid of StartupAcm Module, if StartupAcm
>is in a BiosModule, it will be excluded form that.\n");
>+  printf ("\tBiosModuleAddress      - Address of BiosModule. User should
>ensure there is no overlap.\n");
>+  printf ("\tBiosModuleSize         - Size of BiosModule.\n");
>+  printf ("\tMicrocodeAddress       - Address of Microcode.\n");
>+  printf ("\tMicrocodeSize          - Size of Microcode.\n");
>+  printf ("\tMicrocodeFv            - Name of Microcode.fv file.\n");
>+  printf ("\tMicrocodeBase          - The base address of Microcode.fv in final FD
>image.\n");
>+  printf ("\tMicrocodeRegionOffset  - Offset of Microcode region in input FD
>image.\n");
>+  printf ("\tMicrocodeRegionSize    - Size of Microcode region in input FD
>image.\n");
>+  printf ("\tMicrocodeGuid          - Guid of Microcode Module.\n");
>+  printf ("\t-NA                    - No 0x800 aligned Microcode requirement. No -NA
>means Microcode is 0x800 aligned.\n");
>+  printf ("\tRecordType             - FIT entry record type. User should ensure it is
>ordered.\n");
>+  printf ("\tRecordDataAddress      - FIT entry record data address.\n");
>+  printf ("\tRecordDataSize         - FIT entry record data size.\n");
>+  printf ("\tRecordDataGuid         - FIT entry record data GUID.\n");
>+  printf ("\tRecordBinFile          - FIT entry record data binary file.\n");
>+  printf ("\tFitEntryDefaultVersion - The default version for all FIT table
>entries. 0x%04x is used if this is not specified.\n",
>DEFAULT_FIT_ENTRY_VERSION);
>+  printf ("\tFitHeaderVersion       - The version for FIT header. (Override
>default version)\n");
>+  printf ("\tStartupAcmVersion      - The version for StartupAcm. (Override
>default version)\n");
>+  printf ("\tBiosModuleVersion      - The version for BiosModule. (Override
>default version)\n");
>+  printf ("\tMicrocodeVersion       - The version for Microcode. (Override
>default version)\n");
>+  printf ("\tRecordVersion          - The version for Record. (Override default
>version)\n");
>+  printf ("\tIndexPort              - The Index Port Number.\n");
>+  printf ("\tDataPort               - The Data Port Number.\n");
>+  printf ("\tWidth                  - The Width of the port.\n");
>+  printf ("\tBit                    - The Bit Number of the port.\n");
>+  printf ("\tIndex                  - The Index Number of the port.\n");
>+  printf ("\nUsage (view): %s [-view] InputFile -F <FitTablePointerOffset>\n",
>UTILITY_NAME);
>+  printf ("  Where:\n");
>+  printf ("\tInputFile              - Name of the input file.\n");
>+  printf ("\tFitTablePointerOffset  - FIT table pointer offset from end of file.
>0x%x as default.\n", DEFAULT_FIT_TABLE_POINTER_OFFSET);
>+  printf ("\nTool return values:\n");
>+  printf ("\tSTATUS_SUCCESS=%d, STATUS_WARNING=%d,
>STATUS_ERROR=%d\n", STATUS_SUCCESS, STATUS_WARNING,
>STATUS_ERROR);
>+}
>+
>+VOID *
>+SetMem (
>+  OUT     VOID                      *Buffer,
>+  IN      UINTN                     Length,
>+  IN      UINT8                     Value
>+  )
>+{
>+  //
>+  // Declare the local variables that actually move the data elements as
>+  // volatile to prevent the optimizer from replacing this function with
>+  // the intrinsic memset()
>+  //
>+  volatile UINT8                    *Pointer;
>+
>+  Pointer = (UINT8*)Buffer;
>+  while (Length-- > 0) {
>+    *(Pointer++) = Value;
>+  }
>+  return Buffer;
>+}
>+
>+STATUS
>+ReadInputFile (
>+  IN CHAR8    *FileName,
>+  OUT UINT8   **FileData,
>+  OUT UINT32  *FileSize,
>+  OUT UINT8   **FileBufferRaw OPTIONAL
>+  )
>+/*++
>+
>+Routine Description:
>+
>+  Read input file
>+
>+Arguments:
>+
>+  FileName      - The input file name
>+  FileData      - The input file data, the memory is aligned.
>+  FileSize      - The input file size
>+  FileBufferRaw - The memory to hold input file data. The caller must free the
>memory.
>+
>+Returns:
>+
>+  STATUS_SUCCESS - The file found and data read
>+  STATUS_ERROR   - The file data is not read
>+  STATUS_WARNING - The file is not found
>+
>+--*/
>+{
>+  FILE                        *FpIn;
>+  UINT32                      TempResult;
>+
>+  //
>+  // Open the Input FvRecovery.fv file
>+  //
>+  if ((FpIn = fopen (FileName, "rb")) == NULL) {
>+    //
>+    // Return WARNING, let caller make decision
>+    //
>+//    Error (NULL, 0, 0, "Unable to open file", FileName);
>+    return STATUS_WARNING;
>+  }
>+  //
>+  // Get the Input FvRecovery.fv file size
>+  //
>+  fseek (FpIn, 0, SEEK_END);
>+  *FileSize = ftell (FpIn);
>+  //
>+  // Read the contents of input file to memory buffer
>+  //
>+  if (FileBufferRaw != NULL) {
>+    *FileBufferRaw = (UINT8 *) malloc (*FileSize + 0x10000);
>+    if (NULL == *FileBufferRaw) {
>+      Error (NULL, 0, 0, "No sufficient memory to allocate!", NULL);
>+      fclose (FpIn);
>+      return STATUS_ERROR;
>+    }
>+    TempResult = 0x10000 - (UINT32) ((UINTN)*FileBufferRaw & 0x0FFFF);
>+    *FileData = (UINT8 *)((UINTN)*FileBufferRaw + TempResult);
>+  } else {
>+    *FileData = (UINT8 *) malloc (*FileSize);
>+     if (NULL == *FileData) {
>+      Error (NULL, 0, 0, "No sufficient memory to allocate!", NULL);
>+      fclose (FpIn);
>+      return STATUS_ERROR;
>+    }
>+  }
>+  fseek (FpIn, 0, SEEK_SET);
>+  TempResult = fread (*FileData, 1, *FileSize, FpIn);
>+  if (TempResult != *FileSize) {
>+    Error (NULL, 0, 0, "Read input file error!", NULL);
>+    if (FileBufferRaw != NULL) {
>+      free ((VOID *)*FileBufferRaw);
>+    } else {
>+      free ((VOID *)*FileData);
>+    }
>+    fclose (FpIn);
>+    return STATUS_ERROR;
>+  }
>+
>+  //
>+  // Close the input FvRecovery.fv file
>+  //
>+  fclose (FpIn);
>+
>+  return STATUS_SUCCESS;
>+}
>+
>+UINT8 *
>+FindNextFvHeader (
>+  IN UINT8 *FileBuffer,
>+  IN UINTN  FileLength
>+  )
>+/*++
>+
>+  Routine Description:
>+    Find next FvHeader in the FileBuffer
>+
>+  Parameters:
>+    FileBuffer        -   The start FileBuffer which needs to be searched
>+    FileLength        -   The whole File Length.
>+  Return:
>+    FvHeader          -   The FvHeader is found successfully.
>+    NULL              -   The FvHeader is not found.
>+
>+--*/
>+{
>+  UINT8                       *FileHeader;
>+  EFI_FIRMWARE_VOLUME_HEADER  *FvHeader;
>+  UINT16                      FileChecksum;
>+
>+  FileHeader = FileBuffer;
>+  for (; (UINTN)FileBuffer < (UINTN)FileHeader + FileLength; FileBuffer += 8) {
>+    FvHeader = (EFI_FIRMWARE_VOLUME_HEADER *)FileBuffer;
>+    if (FvHeader->Signature == EFI_FVH_SIGNATURE) {
>+      //
>+      // potential candidate
>+      //
>+
>+      //
>+      // Check checksum
>+      //
>+      if (FvHeader->FvLength > FileLength) {
>+        continue;
>+      }
>+      if (FvHeader->HeaderLength >= FileLength) {
>+        continue;
>+      }
>+      FileChecksum = CalculateChecksum16 ((UINT16 *)FileBuffer, FvHeader-
>>HeaderLength / sizeof (UINT16));
>+      if (FileChecksum != 0) {
>+        continue;
>+      }
>+
>+      //
>+      // Check revision and reserved field
>+      //
>+#if (PI_SPECIFICATION_VERSION < 0x00010000)
>+      if ((FvHeader->Revision == EFI_FVH_REVISION) &&
>+          (FvHeader->Reserved[0] == 0) &&
>+          (FvHeader->Reserved[1] == 0) &&
>+          (FvHeader->Reserved[2] == 0) ){
>+        return FileBuffer;
>+      }
>+#else
>+      if ((FvHeader->Revision == EFI_FVH_PI_REVISION) &&
>+          (FvHeader->Reserved[0] == 0) ){
>+        return FileBuffer;
>+      }
>+#endif
>+    }
>+  }
>+
>+  return NULL;
>+}
>+
>+UINT8  *
>+FindFileFromFvByGuid (
>+  IN UINT8     *FvBuffer,
>+  IN UINT32    FvSize,
>+  IN EFI_GUID  *Guid,
>+  OUT UINT32   *FileSize
>+  )
>+/*++
>+
>+Routine Description:
>+
>+  Find File with GUID in an FV
>+
>+Arguments:
>+
>+  FvBuffer       - FV binary buffer
>+  FvSize         - FV size
>+  Guid           - File GUID value to be searched
>+  FileSize       - Guid File size
>+
>+Returns:
>+
>+  FileLocation   - Guid File location.
>+  NULL           - Guid File is not found.
>+
>+--*/
>+{
>+  EFI_FIRMWARE_VOLUME_HEADER  *FvHeader;
>+  EFI_FFS_FILE_HEADER         *FileHeader;
>+  UINT64                      FvLength;
>+  EFI_GUID                    *TempGuid;
>+  UINT8                       *FixPoint;
>+  UINT32                      Offset;
>+  UINT32                      FileLength;
>+  UINT32                      FileOccupiedSize;
>+
>+  //
>+  // Find the FFS file
>+  //
>+  FvHeader = (EFI_FIRMWARE_VOLUME_HEADER *)FindNextFvHeader
>(FvBuffer, FvSize);
>+  if (NULL == FvHeader) {
>+    return NULL;
>+  }
>+  while (TRUE) {
>+    FvLength         = FvHeader->FvLength;
>+
>+    //
>+    // Prepare to walk the FV image
>+    //
>+    InitializeFvLib (FvHeader, (UINT32)FvLength);
>+
>+    FileHeader       = (EFI_FFS_FILE_HEADER *)((UINTN)FvHeader + FvHeader-
>>HeaderLength);
>+    Offset           = (UINT32) (UINTN) FileHeader - (UINT32) (UINTN) FvHeader;
>+
>+    while (Offset < FvLength) {
>+      TempGuid = (EFI_GUID *)&(FileHeader->Name);
>+      FileLength = (*(UINT32 *)(FileHeader->Size)) & 0x00FFFFFF;
>+      FileOccupiedSize = GETOCCUPIEDSIZE(FileLength, 8);
>+      if ((CompareGuid (TempGuid, Guid)) == 0) {
>+        //
>+        // Good! Find it.
>+        //
>+        FixPoint = ((UINT8 *)FileHeader + sizeof(EFI_FFS_FILE_HEADER));
>+        //
>+        // Find the position of file module, the offset
>+        // between the position and the end of FvRecovery.fv file
>+        // should not exceed 128kB to prevent reset vector from
>+        // outside legacy E and F segment
>+        //
>+        if ((UINTN)FvHeader + FvLength - (UINTN)FixPoint > 0x20000) {
>+  //        printf ("WARNING: The position of file module is not in E and F
>segment!\n");
>+  //        return NULL;
>+        }
>+        *FileSize = FileLength - sizeof(EFI_FFS_FILE_HEADER);
>+  #if (PI_SPECIFICATION_VERSION < 0x00010000)
>+        if (FileHeader->Attributes & FFS_ATTRIB_TAIL_PRESENT) {
>+          *FileSize -= sizeof(EFI_FFS_FILE_TAIL);
>+        }
>+  #endif
>+        return FixPoint;
>+      }
>+      FileHeader = (EFI_FFS_FILE_HEADER *)((UINTN)FileHeader +
>FileOccupiedSize);
>+      Offset = (UINT32) (UINTN) FileHeader - (UINT32) (UINTN) FvHeader;
>+    }
>+
>+    //
>+    // Not found, check next FV
>+    //
>+    if ((UINTN)FvBuffer + FvSize > (UINTN)FvHeader + FvLength) {
>+      FvHeader = (EFI_FIRMWARE_VOLUME_HEADER *)FindNextFvHeader
>((UINT8 *)FvHeader + (UINTN)FvLength, (UINTN)FvBuffer + FvSize -
>((UINTN)FvHeader + (UINTN)FvLength));
>+      if (FvHeader == NULL) {
>+        break;
>+      }
>+    } else {
>+      break;
>+    }
>+  }
>+
>+  //
>+  // Not found
>+  //
>+  return NULL;
>+}
>+
>+BOOLEAN
>+IsGuidData (
>+  IN CHAR8     *StringData,
>+  OUT EFI_GUID *Guid
>+  )
>+/*++
>+
>+Routine Description:
>+
>+  Check whether a string is a GUID
>+
>+Arguments:
>+
>+  StringData  - the String
>+  Guid        - Guid to hold the value
>+
>+Returns:
>+
>+  TRUE  - StringData is a GUID, and Guid field is filled.
>+  FALSE - StringData is not a GUID
>+
>+--*/
>+{
>+  if (strlen (StringData) != strlen ("00000000-0000-0000-0000-000000000000"))
>{
>+    return FALSE;
>+  }
>+  if ((StringData[8] != '-') ||
>+      (StringData[13] != '-') ||
>+      (StringData[18] != '-') ||
>+      (StringData[23] != '-') ) {
>+    return FALSE;
>+  }
>+
>+  StringToGuid (StringData, Guid);
>+
>+  return TRUE;
>+}
>+
>+VOID
>+CheckOverlap (
>+  IN UINT32 Address,
>+  IN UINT32 Size
>+  )
>+{
>+  INTN  Index;
>+
>+  for (Index = 0; Index < (INTN)gFitTableContext.BiosModuleNumber; Index
>++) {
>+    if ((gFitTableContext.BiosModule[Index].Address <= Address) &&
>+        ((gFitTableContext.BiosModule[Index].Size - Size) >= (Address -
>gFitTableContext.BiosModule[Index].Address))) {
>+      UINT32  TempSize;
>+      INT32   SubIndex;
>+
>+      //
>+      // Found overlap, split BiosModuleEntry
>+      // Currently only support StartupAcm in 1 BiosModule. It does not
>support StartupAcm across 2 BiosModule or more.
>+      //
>+      if (gFitTableContext.BiosModuleNumber >= MAX_BIOS_MODULE_ENTRY)
>{
>+        Error (NULL, 0, 0, "Too many Bios Module!", NULL);
>+        return ;
>+      }
>+
>+      if (Address != gFitTableContext.BiosModule[Index].Address) {
>+        //
>+        // Skip the entry whose start address is same as StartupAcm
>+        //
>+
>gFitTableContext.BiosModule[gFitTableContext.BiosModuleNumber].Type
>= FIT_TABLE_TYPE_BIOS_MODULE;
>+
>gFitTableContext.BiosModule[gFitTableContext.BiosModuleNumber].Addres
>s = gFitTableContext.BiosModule[Index].Address;
>+
>gFitTableContext.BiosModule[gFitTableContext.BiosModuleNumber].Size    =
>Address - gFitTableContext.BiosModule[Index].Address;
>+        gFitTableContext.BiosModuleNumber ++;
>+        gFitTableContext.FitEntryNumber++;
>+      }
>+
>+      TempSize = gFitTableContext.BiosModule[Index].Address +
>gFitTableContext.BiosModule[Index].Size;
>+      gFitTableContext.BiosModule[Index].Address = Address + Size;
>+      gFitTableContext.BiosModule[Index].Size    = TempSize -
>gFitTableContext.BiosModule[Index].Address;
>+
>+      if (gFitTableContext.BiosModule[Index].Size == 0) {
>+        //
>+        // remove the entry if size is 0
>+        //
>+        for (SubIndex = Index; SubIndex <
>(INTN)gFitTableContext.BiosModuleNumber - 1; SubIndex ++) {
>+          gFitTableContext.BiosModule[SubIndex].Address =
>gFitTableContext.BiosModule[SubIndex + 1].Address;
>+          gFitTableContext.BiosModule[SubIndex].Size    =
>gFitTableContext.BiosModule[SubIndex + 1].Size;
>+        }
>+        gFitTableContext.BiosModuleNumber --;
>+        gFitTableContext.FitEntryNumber--;
>+      }
>+      break;
>+    }
>+  }
>+}
>+
>+UINT32
>+GetFitEntryNumber (
>+  IN INTN   argc,
>+  IN CHAR8  **argv,
>+  IN UINT8  *FdBuffer,
>+  IN UINT32 FdSize
>+  )
>+/*++
>+
>+Routine Description:
>+
>+  Get FIT entry number and fill global FIT table context, from argument
>+
>+Arguments:
>+
>+  argc           - Number of command line parameters.
>+  argv           - Array of pointers to parameter strings.
>+  FdBuffer       - FD binary buffer
>+  FdSize         - FD size
>+
>+Returns:
>+
>+  FitEntryNumber - The FIT entry number
>+  0              - Argument parse fail
>+
>+*/
>+{
>+  EFI_GUID  Guid;
>+  INTN      Index;
>+  UINT8     *FileBuffer;
>+  UINT32    FileSize;
>+  UINT32    Type;
>+  UINT8     *MicrocodeFileBuffer;
>+  UINT8     *MicrocodeFileBufferRaw;
>+  UINT32    MicrocodeFileSize;
>+  UINT32    MicrocodeBase;
>+  UINT32    MicrocodeSize;
>+  UINT8     *MicrocodeBuffer;
>+  UINT32    MicrocodeRegionOffset;
>+  UINT32    MicrocodeRegionSize;
>+  STATUS    Status;
>+  EFI_FIRMWARE_VOLUME_HEADER  *FvHeader;
>+  UINTN                       FitEntryNumber;
>+  BOOLEAN                     BiosInfoExist;
>+  BIOS_INFO_HEADER            *BiosInfo;
>+  BIOS_INFO_STRUCT            *BiosInfoStruct;
>+  UINTN                       BiosInfoIndex;
>+
>+  //
>+  // Init index
>+  //
>+  Index = 3;
>+  if (((strcmp (argv[1], "-D") == 0) ||
>+       (strcmp (argv[1], "-d") == 0)) ) {
>+    Index ++;
>+  }
>+
>+  //
>+  // Fill Global Version
>+  //
>+  if ((Index + 1 >= argc) ||
>+      ((strcmp (argv[Index], "-V") != 0) &&
>+       (strcmp (argv[Index], "-v") != 0)) ) {
>+    gFitTableContext.GlobalVersion = DEFAULT_FIT_ENTRY_VERSION;
>+  } else {
>+    gFitTableContext.GlobalVersion = xtoi (argv[Index + 1]);
>+    Index += 2;
>+  }
>+
>+  //
>+  // 0. FIT Header
>+  //
>+  gFitTableContext.FitEntryNumber = 1;
>+  if ((Index + 1 >= argc) ||
>+      ((strcmp (argv[Index], "-F") != 0) &&
>+       (strcmp (argv[Index], "-f") != 0)) ) {
>+    //
>+    // Use default address
>+    //
>+    gFitTableContext.FitTablePointerOffset =
>DEFAULT_FIT_TABLE_POINTER_OFFSET;
>+  } else {
>+    //
>+    // Get offset from parameter
>+    //
>+    gFitTableContext.FitTablePointerOffset = xtoi (argv[Index + 1]);
>+    Index += 2;
>+  }
>+
>+  //
>+  // 0.1 FIT Header 2
>+  //
>+  if ((Index + 1 >= argc) ||
>+      ((strcmp (argv[Index], "-F") != 0) &&
>+       (strcmp (argv[Index], "-f") != 0)) ) {
>+    //
>+    // Bypass
>+    //
>+    gFitTableContext.FitTablePointerOffset2 = 0;
>+  } else {
>+    //
>+    // Get offset from parameter
>+    //
>+    gFitTableContext.FitTablePointerOffset2 = xtoi (argv[Index + 1]);
>+    Index += 2;
>+  }
>+
>+  //
>+  // 0.2 FIT Header version
>+  //
>+  if ((Index + 1 >= argc) ||
>+      ((strcmp (argv[Index], "-V") != 0) &&
>+       (strcmp (argv[Index], "-v") != 0)) ) {
>+    //
>+    // Bypass
>+    //
>+    gFitTableContext.FitHeaderVersion = gFitTableContext.GlobalVersion;
>+  } else {
>+    //
>+    // Get offset from parameter
>+    //
>+    gFitTableContext.FitHeaderVersion = xtoi (argv[Index + 1]);
>+    Index += 2;
>+  }
>+
>+  //
>+  // 0.3 Microcode alignment
>+  //
>+  if ((Index >= argc) ||
>+      ((strcmp (argv[Index], "-NA") != 0) &&
>+       (strcmp (argv[Index], "-na") != 0)) ) {
>+    //
>+    // by pass
>+    //
>+    gFitTableContext.MicrocodeAlignment = TRUE;
>+  } else {
>+    //
>+    // no alignment
>+    //
>+    gFitTableContext.MicrocodeAlignment = FALSE;
>+    Index += 1;
>+  }
>+
>+  //
>+  // 0.4 Clear FIT table related memory
>+  //
>+  if ((Index >= argc) ||
>+      ((strcmp (argv[Index], "-CLEAR") != 0) &&
>+       (strcmp (argv[Index], "-clear") != 0)) ) {
>+    //
>+    // by pass
>+    //
>+    gFitTableContext.Clear = FALSE;
>+  } else {
>+    //
>+    // Clear FIT table
>+    //
>+    gFitTableContext.Clear = TRUE;
>+    //
>+    // Do not parse any more
>+    //
>+    return 0;
>+  }
>+
>+  //
>+  // 0.5 BiosInfo
>+  //
>+  if ((Index + 1 >= argc) ||
>+      ((strcmp (argv[Index], "-I") != 0) &&
>+       (strcmp (argv[Index], "-i") != 0)) ) {
>+    //
>+    // Bypass
>+    //
>+    BiosInfoExist = FALSE;
>+  } else {
>+    //
>+    // Get offset from parameter
>+    //
>+    BiosInfoExist = TRUE;
>+    if (IsGuidData (argv[Index + 1], &Guid)) {
>+      FileBuffer = FindFileFromFvByGuid (FdBuffer, FdSize, &Guid, &FileSize);
>+      if (FileBuffer == NULL) {
>+        Error (NULL, 0, 0, "-I Parameter incorrect, GUID not found!", "%s",
>argv[Index + 1]);
>+        // not found
>+        return 0;
>+      }
>+      BiosInfo = (BIOS_INFO_HEADER *)FileBuffer;
>+      for (BiosInfoIndex = 0; BiosInfoIndex < FileSize; BiosInfoIndex++) {
>+        if (((BIOS_INFO_HEADER *)(FileBuffer + BiosInfoIndex))->Signature ==
>BIOS_INFO_SIGNATURE) {
>+          BiosInfo = (BIOS_INFO_HEADER *)(FileBuffer + BiosInfoIndex);
>+        }
>+      }
>+      if (BiosInfo->Signature != BIOS_INFO_SIGNATURE) {
>+        Error (NULL, 0, 0, "-I Parameter incorrect, Signature Error!", NULL);
>+        // not found
>+        return 0;
>+      }
>+      BiosInfoStruct = (BIOS_INFO_STRUCT *)(BiosInfo + 1);
>+
>+      for (BiosInfoIndex = 0; BiosInfoIndex < BiosInfo->EntryCount;
>BiosInfoIndex++) {
>+        if ((BiosInfoStruct[BiosInfoIndex].Attributes &
>BIOS_INFO_STRUCT_ATTRIBUTE_GENERAL_EXCLUDE_FROM_FIT) != 0) {
>+          continue;
>+        }
>+        switch (BiosInfoStruct[BiosInfoIndex].Type) {
>+        case FIT_TABLE_TYPE_HEADER:
>+          Error (NULL, 0, 0, "-I Parameter incorrect, Header Type unsupported!",
>NULL);
>+          return 0;
>+        case FIT_TABLE_TYPE_STARTUP_ACM:
>+          if (gFitTableContext.StartupAcm.Type != 0) {
>+            Error (NULL, 0, 0, "-I Parameter incorrect, Duplicated StartupAcm!",
>NULL);
>+            return 0;
>+          }
>+          gFitTableContext.StartupAcm.Type    =
>FIT_TABLE_TYPE_STARTUP_ACM;
>+          gFitTableContext.StartupAcm.Address =
>(UINT32)BiosInfoStruct[BiosInfoIndex].Address;
>+          gFitTableContext.StartupAcm.Size    =
>(UINT32)BiosInfoStruct[BiosInfoIndex].Size;
>+          gFitTableContext.StartupAcmVersion  =
>BiosInfoStruct[BiosInfoIndex].Version;
>+          gFitTableContext.FitEntryNumber ++;
>+          break;
>+        case FIT_TABLE_TYPE_BIOS_MODULE:
>+          if ((BiosInfoStruct[BiosInfoIndex].Attributes &
>BIOS_INFO_STRUCT_ATTRIBUTE_BIOS_POST_IBB) != 0) {
>+            continue;
>+          }
>+          if (gFitTableContext.BiosModuleNumber >=
>MAX_BIOS_MODULE_ENTRY) {
>+            Error (NULL, 0, 0, "-I Parameter incorrect, Too many Bios Module!",
>NULL);
>+            return 0;
>+          }
>+
>gFitTableContext.BiosModule[gFitTableContext.BiosModuleNumber].Type
>= FIT_TABLE_TYPE_BIOS_MODULE;
>+
>gFitTableContext.BiosModule[gFitTableContext.BiosModuleNumber].Addres
>s = (UINT32)BiosInfoStruct[BiosInfoIndex].Address;
>+
>gFitTableContext.BiosModule[gFitTableContext.BiosModuleNumber].Size    =
>(UINT32)BiosInfoStruct[BiosInfoIndex].Size;
>+          gFitTableContext.BiosModuleVersion =
>BiosInfoStruct[BiosInfoIndex].Version;
>+          gFitTableContext.BiosModuleNumber ++;
>+          gFitTableContext.FitEntryNumber ++;
>+          break;
>+        case FIT_TABLE_TYPE_MICROCODE:
>+          if ((BiosInfoStruct[BiosInfoIndex].Attributes &
>BIOS_INFO_STRUCT_ATTRIBUTE_MICROCODE_WHOLE_REGION) == 0) {
>+            if (gFitTableContext.MicrocodeNumber >= MAX_MICROCODE_ENTRY)
>{
>+              Error (NULL, 0, 0, "-I Parameter incorrect, Too many Microcode!",
>NULL);
>+              return 0;
>+            }
>+
>gFitTableContext.Microcode[gFitTableContext.MicrocodeNumber].Type    =
>FIT_TABLE_TYPE_MICROCODE;
>+
>gFitTableContext.Microcode[gFitTableContext.MicrocodeNumber].Address =
>(UINT32)BiosInfoStruct[BiosInfoIndex].Address;
>+
>gFitTableContext.Microcode[gFitTableContext.MicrocodeNumber].Size    =
>(UINT32)BiosInfoStruct[BiosInfoIndex].Size;
>+            gFitTableContext.MicrocodeVersion =
>BiosInfoStruct[BiosInfoIndex].Version;
>+            gFitTableContext.MicrocodeNumber++;
>+            gFitTableContext.FitEntryNumber++;
>+          } else {
>+            MicrocodeRegionOffset =
>(UINT32)BiosInfoStruct[BiosInfoIndex].Address;
>+            MicrocodeRegionSize   = (UINT32)BiosInfoStruct[BiosInfoIndex].Size;
>+            if (MicrocodeRegionOffset == 0) {
>+              Error (NULL, 0, 0, "-I Parameter incorrect, MicrocodeRegionOffset is 0",
>NULL);
>+              return 0;
>+            }
>+            if (MicrocodeRegionSize == 0) {
>+              Error (NULL, 0, 0, "-I Parameter incorrect, MicrocodeRegionSize is 0",
>NULL);
>+              return 0;
>+            }
>+            if (MicrocodeRegionSize > FdSize) {
>+              Error (NULL, 0, 0, "-I Parameter incorrect, MicrocodeRegionSize too
>large", NULL);
>+              return 0;
>+            }
>+
>+            MicrocodeFileBuffer = FLASH_TO_MEMORY (MicrocodeRegionOffset,
>FdBuffer, FdSize);
>+            MicrocodeFileSize = MicrocodeRegionSize;
>+            MicrocodeBase = MicrocodeRegionOffset;
>+
>+            FvHeader = (EFI_FIRMWARE_VOLUME_HEADER
>*)MicrocodeFileBuffer;
>+            if (FvHeader->Signature == EFI_FVH_SIGNATURE) {
>+              // Skip FV header + FFS header
>+              MicrocodeBuffer = MicrocodeFileBuffer +
>sizeof(EFI_FIRMWARE_VOLUME_HEADER) +
>sizeof(EFI_FV_BLOCK_MAP_ENTRY) + sizeof(EFI_FFS_FILE_HEADER);
>+            } else {
>+              MicrocodeBuffer = MicrocodeFileBuffer;
>+            }
>+            while ((UINT32)(MicrocodeBuffer - MicrocodeFileBuffer) <
>MicrocodeFileSize) {
>+              if (*(UINT32 *)(MicrocodeBuffer) != 0x1) { // HeaderVersion
>+                break;
>+              }
>+              if (*(UINT32 *)(MicrocodeBuffer + 20) != 0x1) { // LoaderVersion
>+                break;
>+              }
>+              if (*(UINT32 *)(MicrocodeBuffer + 28) == 0) { // DataSize
>+                MicrocodeSize = 2048;
>+              } else {
>+                //
>+                // MCU might be put at 2KB alignment, if so, we need to adjust the
>size as 2KB alignment.
>+                //
>+                if (gFitTableContext.MicrocodeAlignment) {
>+                  MicrocodeSize = (*(UINT32 *)(MicrocodeBuffer + 32) +
>MICROCODE_ALIGNMENT) & ~MICROCODE_ALIGNMENT;
>+                } else {
>+                  MicrocodeSize = (*(UINT32 *)(MicrocodeBuffer + 32));
>+                }
>+              }
>+
>+              //
>+              // Add Microcode
>+              //
>+              if (gFitTableContext.MicrocodeNumber >= MAX_MICROCODE_ENTRY)
>{
>+                printf ("-I Parameter incorrect, Too many Microcode!\n");
>+                return 0;
>+              }
>+
>gFitTableContext.Microcode[gFitTableContext.MicrocodeNumber].Type =
>FIT_TABLE_TYPE_MICROCODE;
>+
>gFitTableContext.Microcode[gFitTableContext.MicrocodeNumber].Address =
>MicrocodeBase + ((UINT32) (UINTN) MicrocodeBuffer - (UINT32) (UINTN)
>MicrocodeFileBuffer);
>+
>gFitTableContext.Microcode[gFitTableContext.MicrocodeNumber].Size =
>MicrocodeSize;
>+              gFitTableContext.MicrocodeNumber++;
>+              gFitTableContext.FitEntryNumber++;
>+
>+              MicrocodeBuffer += MicrocodeSize;
>+            }
>+          }
>+          break;
>+        case FIT_TABLE_TYPE_TPM_POLICY:
>+        case FIT_TABLE_TYPE_BIOS_POLICY:
>+        case FIT_TABLE_TYPE_TXT_POLICY:
>+        case FIT_TABLE_TYPE_KEY_MANIFEST:
>+        case FIT_TABLE_TYPE_BOOT_POLICY_MANIFEST:
>+        case FIT_TABLE_TYPE_BIOS_DATA_AREA:
>+        case FIT_TABLE_TYPE_CSE_SECURE_BOOT:
>+        default :
>+          if (BiosInfoStruct[BiosInfoIndex].Version != 0) {
>+            if (gFitTableContext.OptionalModuleNumber >=
>MAX_OPTIONAL_ENTRY) {
>+              Error (NULL, 0, 0, "-I Parameter incorrect, Too many Optional
>Module!", NULL);
>+              return 0;
>+            }
>+
>gFitTableContext.OptionalModule[gFitTableContext.OptionalModuleNumber
>].Type    = BiosInfoStruct[BiosInfoIndex].Type;
>+
>gFitTableContext.OptionalModule[gFitTableContext.OptionalModuleNumber
>].Address = (UINT32)BiosInfoStruct[BiosInfoIndex].Address;
>+
>gFitTableContext.OptionalModule[gFitTableContext.OptionalModuleNumber
>].Size    = (UINT32)BiosInfoStruct[BiosInfoIndex].Size;
>+
>gFitTableContext.OptionalModule[gFitTableContext.OptionalModuleNumber
>].Version = BiosInfoStruct[BiosInfoIndex].Version;
>+            gFitTableContext.OptionalModuleNumber++;
>+            gFitTableContext.FitEntryNumber++;
>+          } else {
>+            if (gFitTableContext.PortModuleNumber >= MAX_PORT_ENTRY) {
>+              Error (NULL, 0, 0, "-I Parameter incorrect, Too many Port Module!",
>NULL);
>+              return 0;
>+            }
>+
>gFitTableContext.PortModule[gFitTableContext.PortModuleNumber].Type
>= BiosInfoStruct[BiosInfoIndex].Type;
>+
>gFitTableContext.PortModule[gFitTableContext.PortModuleNumber].Addres
>s = (UINT32)BiosInfoStruct[BiosInfoIndex].Address;
>+
>gFitTableContext.PortModule[gFitTableContext.PortModuleNumber].Size    =
>(UINT32)(BiosInfoStruct[BiosInfoIndex].Address >> 32);
>+
>gFitTableContext.PortModule[gFitTableContext.PortModuleNumber].Version
>= BiosInfoStruct[BiosInfoIndex].Version;
>+            gFitTableContext.PortModuleNumber++;
>+            gFitTableContext.FitEntryNumber++;
>+          }
>+          break;
>+        }
>+      }
>+
>+    } else {
>+      Error (NULL, 0, 0, "-I Parameter incorrect, expect GUID!", NULL);
>+      return 0;
>+    }
>+    Index += 2;
>+  }
>+
>+  //
>+  // 1. StartupAcm
>+  //
>+  do {
>+    if ((Index + 1 >= argc) ||
>+        ((strcmp (argv[Index], "-S") != 0) &&
>+         (strcmp (argv[Index], "-s") != 0)) ) {
>+      if (BiosInfoExist && (gFitTableContext.StartupAcm.Type ==
>FIT_TABLE_TYPE_STARTUP_ACM)) {
>+        break;
>+      }
>+//      Error (NULL, 0, 0, "-S Parameter incorrect, expect -S!", NULL);
>+//      return 0;
>+      printf ("-S not found. WARNING!\n");
>+      break;
>+    }
>+    if (IsGuidData (argv[Index + 1], &Guid)) {
>+      FileBuffer = FindFileFromFvByGuid (FdBuffer, FdSize, &Guid, &FileSize);
>+      if (FileBuffer == NULL) {
>+        Error (NULL, 0, 0, "-S Parameter incorrect, GUID not found!", "%s",
>argv[Index + 1]);
>+        // not found
>+        return 0;
>+      }
>+      FileBuffer = (UINT8 *)MEMORY_TO_FLASH (FileBuffer, FdBuffer, FdSize);
>+      Index += 2;
>+    } else {
>+      if (Index + 2 >= argc) {
>+        Error (NULL, 0, 0, "-S Parameter incorrect, expect Address Size!", NULL);
>+        return 0;
>+      }
>+      FileBuffer = (UINT8 *) (UINTN) xtoi (argv[Index + 1]);
>+      FileSize = xtoi (argv[Index + 2]);
>+      Index += 3;
>+    }
>+    if (gFitTableContext.StartupAcm.Type != 0) {
>+      Error (NULL, 0, 0, "-S Parameter incorrect, Duplicated StartupAcm!", NULL);
>+      return 0;
>+    }
>+    gFitTableContext.StartupAcm.Type = FIT_TABLE_TYPE_STARTUP_ACM;
>+    gFitTableContext.StartupAcm.Address = (UINT32) (UINTN) FileBuffer;
>+    gFitTableContext.StartupAcm.Size = FileSize;
>+    gFitTableContext.FitEntryNumber ++;
>+
>+    //
>+    // 1.1 StartupAcm version
>+    //
>+    if ((Index + 1 >= argc) ||
>+        ((strcmp (argv[Index], "-V") != 0) &&
>+         (strcmp (argv[Index], "-v") != 0)) ) {
>+      //
>+      // Bypass
>+      //
>+      gFitTableContext.StartupAcmVersion = gFitTableContext.GlobalVersion;
>+    } else {
>+      //
>+      // Get offset from parameter
>+      //
>+      gFitTableContext.StartupAcmVersion = xtoi (argv[Index + 1]);
>+      Index += 2;
>+    }
>+  } while (FALSE);
>+
>+  //
>+  // 2. BiosModule
>+  //
>+  do {
>+    if ((Index + 2 >= argc) ||
>+        ((strcmp (argv[Index], "-B") != 0) &&
>+         (strcmp (argv[Index], "-b") != 0)) ) {
>+      if (BiosInfoExist && (gFitTableContext.BiosModuleNumber != 0)) {
>+        break;
>+      }
>+//      Error (NULL, 0, 0, "-B Parameter incorrect, expect -B!", NULL);
>+//      return 0;
>+      printf ("-B not found. WARNING!\n");
>+      break;
>+    }
>+
>+    FileBuffer = (UINT8 *) (UINTN) xtoi (argv[Index + 1]);
>+    FileSize = xtoi (argv[Index + 2]);
>+
>gFitTableContext.BiosModule[gFitTableContext.BiosModuleNumber].Type =
>FIT_TABLE_TYPE_BIOS_MODULE;
>+
>gFitTableContext.BiosModule[gFitTableContext.BiosModuleNumber].Addres
>s = (UINT32) (UINTN) FileBuffer;
>+    gFitTableContext.BiosModule[gFitTableContext.BiosModuleNumber].Size
>= FileSize;
>+    gFitTableContext.BiosModuleNumber ++;
>+    gFitTableContext.FitEntryNumber ++;
>+
>+    while (TRUE) {
>+      Index += 3;
>+      if (Index + 2 >= argc) {
>+        break;
>+      }
>+      if ((strcmp (argv[Index], "-B") != 0) &&
>+          (strcmp (argv[Index], "-b") != 0) ) {
>+        break;
>+      }
>+      if (gFitTableContext.BiosModuleNumber >= MAX_BIOS_MODULE_ENTRY)
>{
>+        Error (NULL, 0, 0, "-B Parameter incorrect, Too many Bios Module!",
>NULL);
>+        return 0;
>+      }
>+      FileBuffer = (UINT8 *) (UINTN) xtoi (argv[Index + 1]);
>+      FileSize = xtoi (argv[Index + 2]);
>+
>gFitTableContext.BiosModule[gFitTableContext.BiosModuleNumber].Type =
>FIT_TABLE_TYPE_BIOS_MODULE;
>+
>gFitTableContext.BiosModule[gFitTableContext.BiosModuleNumber].Addres
>s = (UINT32) (UINTN) FileBuffer;
>+
>gFitTableContext.BiosModule[gFitTableContext.BiosModuleNumber].Size =
>FileSize;
>+      gFitTableContext.BiosModuleNumber ++;
>+      gFitTableContext.FitEntryNumber++;
>+    }
>+
>+    //
>+    // 2.1 BiosModule version
>+    //
>+    if ((Index + 1 >= argc) ||
>+        ((strcmp (argv[Index], "-V") != 0) &&
>+         (strcmp (argv[Index], "-v") != 0)) ) {
>+      //
>+      // Bypass
>+      //
>+      gFitTableContext.BiosModuleVersion = gFitTableContext.GlobalVersion;
>+    } else {
>+      //
>+      // Get offset from parameter
>+      //
>+      gFitTableContext.BiosModuleVersion = xtoi (argv[Index + 1]);
>+      Index += 2;
>+    }
>+  } while (FALSE);
>+
>+  //
>+  // 3. Microcode
>+  //
>+  while (TRUE) {
>+    if (Index + 1 >= argc) {
>+      break;
>+    }
>+    if ((strcmp (argv[Index], "-M") != 0) &&
>+        (strcmp (argv[Index], "-m") != 0) ) {
>+      break;
>+    }
>+    if (IsGuidData (argv[Index + 2], &Guid)) {
>+      Error (NULL, 0, 0, "-M Parameter incorrect, GUID unsupported!", NULL);
>+      return 0;
>+    } else {
>+      if (Index + 2 >= argc) {
>+        break;
>+      }
>+      FileBuffer = (UINT8 *) (UINTN) xtoi (argv[Index + 1]);
>+      FileSize = xtoi (argv[Index + 2]);
>+      Index += 3;
>+    }
>+    if (gFitTableContext.MicrocodeNumber >= MAX_MICROCODE_ENTRY) {
>+      Error (NULL, 0, 0, "-M Parameter incorrect, Too many Microcode!", NULL);
>+      return 0;
>+    }
>+    gFitTableContext.Microcode[gFitTableContext.MicrocodeNumber].Type =
>FIT_TABLE_TYPE_MICROCODE;
>+
>gFitTableContext.Microcode[gFitTableContext.MicrocodeNumber].Address =
>(UINT32) (UINTN) FileBuffer;
>+    gFitTableContext.Microcode[gFitTableContext.MicrocodeNumber].Size =
>FileSize;
>+    gFitTableContext.MicrocodeNumber++;
>+    gFitTableContext.FitEntryNumber++;
>+  }
>+
>+  //
>+  // 3.1 MicrocodeFv
>+  //
>+  while (TRUE) {
>+    if (Index + 1 >= argc) {
>+      break;
>+    }
>+    if ((strcmp (argv[Index], "-U") != 0) &&
>+        (strcmp (argv[Index], "-u") != 0) ) {
>+      break;
>+    }
>+    //
>+    // Get Fv
>+    //
>+    if (IsGuidData (argv[Index + 1], &Guid)) {
>+      MicrocodeFileBuffer = FindFileFromFvByGuid (FdBuffer, FdSize, &Guid,
>&MicrocodeFileSize);
>+      if (MicrocodeFileBuffer == NULL) {
>+        Error (NULL, 0, 0, "-U Parameter incorrect, GUID not found!", "%s",
>argv[Index + 1]);
>+        // not found
>+        return 0;
>+      }
>+      Index += 2;
>+
>+      MicrocodeBuffer = MicrocodeFileBuffer;
>+      MicrocodeFileBufferRaw = NULL;
>+      MicrocodeRegionOffset = MEMORY_TO_FLASH (MicrocodeFileBuffer,
>FdBuffer, FdSize);
>+      MicrocodeRegionSize   = 0;
>+      MicrocodeBase = MicrocodeRegionOffset;
>+
>+    } else {
>+      if (Index + 2 >= argc) {
>+        break;
>+      }
>+      Status = ReadInputFile (argv[Index + 1], &MicrocodeFileBuffer,
>&MicrocodeFileSize, &MicrocodeFileBufferRaw);
>+      if (Status != STATUS_SUCCESS) {
>+        MicrocodeRegionOffset = xtoi (argv[Index + 1]);
>+        MicrocodeRegionSize   = xtoi (argv[Index + 2]);
>+
>+        if (MicrocodeRegionOffset == 0) {
>+          Error (NULL, 0, 0, "-U Parameter incorrect, MicrocodeRegionOffset is 0,
>or unable to open file", "%s", argv[Index + 1]);
>+          return 0;
>+        }
>+        if (MicrocodeRegionSize == 0) {
>+          Error (NULL, 0, 0, "-U Parameter incorrect, MicrocodeRegionSize is 0",
>NULL);
>+          return 0;
>+        }
>+        if (MicrocodeRegionSize > FdSize) {
>+          Error (NULL, 0, 0, "-U Parameter incorrect, MicrocodeRegionSize too
>large", NULL);
>+          return 0;
>+        }
>+
>+        Index += 3;
>+
>+        MicrocodeFileBufferRaw = NULL;
>+        MicrocodeFileBuffer = FLASH_TO_MEMORY (MicrocodeRegionOffset,
>FdBuffer, FdSize);
>+        MicrocodeFileSize = MicrocodeRegionSize;
>+        MicrocodeBase = MicrocodeRegionOffset;
>+
>+        FvHeader = (EFI_FIRMWARE_VOLUME_HEADER *)MicrocodeFileBuffer;
>+        if (FvHeader->Signature == EFI_FVH_SIGNATURE) {
>+          // Skip FV header + FFS header
>+          MicrocodeBuffer = MicrocodeFileBuffer +
>sizeof(EFI_FIRMWARE_VOLUME_HEADER) +
>sizeof(EFI_FV_BLOCK_MAP_ENTRY) + sizeof(EFI_FFS_FILE_HEADER);
>+        } else {
>+          MicrocodeBuffer = MicrocodeFileBuffer;
>+        }
>+      } else {
>+        MicrocodeBase = xtoi (argv[Index + 2]);
>+        Index += 3;
>+        MicrocodeRegionOffset = 0;
>+        MicrocodeRegionSize   = 0;
>+
>+        FvHeader = (EFI_FIRMWARE_VOLUME_HEADER *)MicrocodeFileBuffer;
>+        if (FvHeader->Signature == EFI_FVH_SIGNATURE) {
>+          // Skip FV header + FFS header
>+          MicrocodeBuffer = MicrocodeFileBuffer +
>sizeof(EFI_FIRMWARE_VOLUME_HEADER) +
>sizeof(EFI_FV_BLOCK_MAP_ENTRY) + sizeof(EFI_FFS_FILE_HEADER);
>+        } else {
>+          MicrocodeBuffer = MicrocodeFileBuffer;
>+        }
>+      }
>+    }
>+    while ((UINT32)(MicrocodeBuffer - MicrocodeFileBuffer) <
>MicrocodeFileSize) {
>+      if (*(UINT32 *)(MicrocodeBuffer) != 0x1) { // HeaderVersion
>+        break;
>+      }
>+      if (*(UINT32 *)(MicrocodeBuffer + 20) != 0x1) { // LoaderVersion
>+        break;
>+      }
>+      if (*(UINT32 *)(MicrocodeBuffer + 28) == 0) { // DataSize
>+        MicrocodeSize = 2048;
>+      } else {
>+        //
>+        // MCU might be put at 2KB alignment, if so, we need to adjust the size
>as 2KB alignment.
>+        //
>+        if (gFitTableContext.MicrocodeAlignment) {
>+          MicrocodeSize = (*(UINT32 *)(MicrocodeBuffer + 32) +
>MICROCODE_ALIGNMENT) & ~MICROCODE_ALIGNMENT;
>+        } else {
>+          MicrocodeSize = (*(UINT32 *)(MicrocodeBuffer + 32));
>+        }
>+      }
>+
>+      //
>+      // Add Microcode
>+      //
>+      if (gFitTableContext.MicrocodeNumber >= MAX_MICROCODE_ENTRY) {
>+        printf ("-U Parameter incorrect, Too many Microcode!\n");
>+        return 0;
>+      }
>+      gFitTableContext.Microcode[gFitTableContext.MicrocodeNumber].Type
>= FIT_TABLE_TYPE_MICROCODE;
>+
>gFitTableContext.Microcode[gFitTableContext.MicrocodeNumber].Address =
>MicrocodeBase + ((UINT32) (UINTN) MicrocodeBuffer - (UINT32) (UINTN)
>MicrocodeFileBuffer);
>+      gFitTableContext.Microcode[gFitTableContext.MicrocodeNumber].Size =
>MicrocodeSize;
>+      gFitTableContext.MicrocodeNumber++;
>+      gFitTableContext.FitEntryNumber++;
>+
>+      MicrocodeBuffer += MicrocodeSize;
>+    }
>+
>+    if (MicrocodeFileBufferRaw != NULL) {
>+      free ((VOID *)MicrocodeFileBufferRaw);
>+      MicrocodeFileBufferRaw = NULL;
>+    }
>+  }
>+
>+  //
>+  // 3.3 Microcode version
>+  //
>+  if ((Index + 1 >= argc) ||
>+      ((strcmp (argv[Index], "-V") != 0) &&
>+       (strcmp (argv[Index], "-v") != 0)) ) {
>+    //
>+    // Bypass
>+    //
>+    gFitTableContext.MicrocodeVersion = gFitTableContext.GlobalVersion;
>+  } else {
>+    //
>+    // Get offset from parameter
>+    //
>+    gFitTableContext.MicrocodeVersion = xtoi (argv[Index + 1]);
>+    Index += 2;
>+  }
>+
>+  //
>+  // 4. Optional type
>+  //
>+  while (TRUE) {
>+    if (Index + 2 >= argc) {
>+      break;
>+    }
>+    if ((strcmp (argv[Index], "-O") != 0) &&
>+        (strcmp (argv[Index], "-o") != 0) ) {
>+      break;
>+    }
>+    Type = xtoi (argv[Index + 1]);
>+    //
>+    // 1st, try GUID
>+    //
>+    if (IsGuidData (argv[Index + 2], &Guid)) {
>+      FileBuffer = FindFileFromFvByGuid (FdBuffer, FdSize, &Guid, &FileSize);
>+      if (FileBuffer == NULL) {
>+        Error (NULL, 0, 0, "-O Parameter incorrect, GUID not found!", "%s",
>argv[Index + 2]);
>+        // not found
>+        return 0;
>+      }
>+      if (FileSize >= 0x80000000) {
>+        Error (NULL, 0, 0, "-O Parameter incorrect, FileSize too large!", NULL);
>+        return 0;
>+      }
>+      FileBuffer = (UINT8 *)MEMORY_TO_FLASH (FileBuffer, FdBuffer, FdSize);
>+      Index += 3;
>+    } else {
>+      //
>+      // 2nd, try file
>+      //
>+      Status = ReadInputFile (argv[Index + 2], &FileBuffer, &FileSize, NULL);
>+      if (Status == STATUS_SUCCESS) {
>+        if (FileSize >= 0x80000000) {
>+          Error (NULL, 0, 0, "-O Parameter incorrect, FileSize too large!", NULL);
>+          free (FileBuffer);
>+          return 0;
>+        }
>+        //
>+        // Set the most significant bit
>+        // It means the data in memory, not in flash yet.
>+        // Assume the file size should < 2G.
>+        //
>+        FileSize |= 0x80000000;
>+        Index += 3;
>+      } else {
>+        //
>+        // 3rd, try <RESERVE, Length>
>+        //
>+        if (Index + 3 >= argc) {
>+          break;
>+        }
>+        if ((strcmp (argv[Index + 2], "RESERVE") == 0) ||
>+            (strcmp (argv[Index + 2], "reserve") == 0)) {
>+          FileSize = xtoi (argv[Index + 3]);
>+          if (FileSize >= 0x80000000) {
>+            Error (NULL, 0, 0, "-O Parameter incorrect, FileSize too large!", NULL);
>+            return 0;
>+          }
>+          FileBuffer = malloc (FileSize);
>+          if (FileBuffer == NULL) {
>+            Error (NULL, 0, 0, "No sufficient memory to allocate!", NULL);
>+            return 0;
>+          }
>+          SetMem (FileBuffer, FileSize, 0xFF);
>+          //
>+          // Set the most significant bit
>+          // It means the data in memory, not in flash yet.
>+          // Assume the file size should < 2G.
>+          //
>+          FileSize |= 0x80000000;
>+          Index += 4;
>+        } else {
>+          //
>+          // 4th, try <Address, Length>
>+          //
>+          if (Index + 3 >= argc) {
>+            break;
>+          }
>+          FileBuffer = (UINT8 *) (UINTN) xtoi (argv[Index + 2]);
>+          FileSize = xtoi (argv[Index + 3]);
>+          if (FileSize >= 0x80000000) {
>+            Error (NULL, 0, 0, "-O Parameter incorrect, FileSize too large!", NULL);
>+            return 0;
>+          }
>+          Index += 4;
>+        }
>+      }
>+    }
>+    if (gFitTableContext.OptionalModuleNumber >= MAX_OPTIONAL_ENTRY)
>{
>+      Error (NULL, 0, 0, "-O Parameter incorrect, Too many Optional Module!",
>NULL);
>+      free (FileBuffer);
>+      return 0;
>+    }
>+
>gFitTableContext.OptionalModule[gFitTableContext.OptionalModuleNumber
>].Type = Type;
>+
>gFitTableContext.OptionalModule[gFitTableContext.OptionalModuleNumber
>].Address = (UINT32) (UINTN) FileBuffer;
>+
>gFitTableContext.OptionalModule[gFitTableContext.OptionalModuleNumber
>].Size = FileSize;
>+
>+    //
>+    // 4.1 Optional Module version
>+    //
>+    if ((Index + 1 >= argc) ||
>+        ((strcmp (argv[Index], "-V") != 0) &&
>+         (strcmp (argv[Index], "-v") != 0)) ) {
>+      //
>+      // Bypass
>+      //
>+
>gFitTableContext.OptionalModule[gFitTableContext.OptionalModuleNumber
>].Version = gFitTableContext.GlobalVersion;
>+    } else {
>+      //
>+      // Get offset from parameter
>+      //
>+
>gFitTableContext.OptionalModule[gFitTableContext.OptionalModuleNumber
>].Version = xtoi (argv[Index + 1]);
>+      Index += 2;
>+    }
>+
>+    gFitTableContext.OptionalModuleNumber ++;
>+    gFitTableContext.FitEntryNumber++;
>+  }
>+
>+  //
>+  // 5. Port type
>+  //
>+  while (TRUE) {
>+    if (Index + 6 >= argc) {
>+      break;
>+    }
>+    if ((strcmp (argv[Index], "-P") != 0) &&
>+        (strcmp (argv[Index], "-p") != 0) ) {
>+      break;
>+    }
>+
>+    Type = xtoi (argv[Index + 1]);
>+    if (gFitTableContext.PortModuleNumber >= MAX_PORT_ENTRY) {
>+      printf ("-P Parameter incorrect, Too many Port Module!\n");
>+      return 0;
>+    }
>+
>+
>gFitTableContext.PortModule[gFitTableContext.PortModuleNumber].Type =
>Type;
>+
>gFitTableContext.PortModule[gFitTableContext.PortModuleNumber].Addres
>s = (UINT16)xtoi (argv[Index + 2]) + ((UINT16)xtoi (argv[Index + 3]) << 16);
>+    gFitTableContext.PortModule[gFitTableContext.PortModuleNumber].Size
>= (UINT8)xtoi (argv[Index + 4]) + ((UINT8)xtoi (argv[Index + 5]) << 8) +
>((UINT16)xtoi (argv[Index + 6]) << 16);
>+    Index += 7;
>+
>+    //
>+    // 5.1 Port Module version
>+    //
>+    if ((Index + 1 >= argc) ||
>+        ((strcmp (argv[Index], "-V") != 0) &&
>+         (strcmp (argv[Index], "-v") != 0)) ) {
>+      //
>+      // Bypass
>+      //
>+
>gFitTableContext.PortModule[gFitTableContext.PortModuleNumber].Version
>= 0;
>+    } else {
>+      //
>+      // Get offset from parameter
>+      //
>+
>gFitTableContext.PortModule[gFitTableContext.PortModuleNumber].Version
>= xtoi (argv[Index + 1]);
>+      Index += 2;
>+    }
>+
>+    gFitTableContext.PortModuleNumber++;
>+    gFitTableContext.FitEntryNumber++;
>+  }
>+
>+  //
>+  // Final: Check StartupAcm in BiosModule.
>+  //
>+  CheckOverlap (gFitTableContext.StartupAcm.Address,
>gFitTableContext.StartupAcm.Size);
>+  FitEntryNumber = gFitTableContext.FitEntryNumber;
>+  for (Index = 0; Index < (INTN)gFitTableContext.OptionalModuleNumber;
>Index++) {
>+    if ((gFitTableContext.OptionalModule[Index].Type ==
>FIT_TABLE_TYPE_BIOS_POLICY) ||
>+        (gFitTableContext.OptionalModule[Index].Type ==
>FIT_TABLE_TYPE_KEY_MANIFEST) ||
>+        (gFitTableContext.OptionalModule[Index].Type ==
>FIT_TABLE_TYPE_BOOT_POLICY_MANIFEST) ||
>+        (gFitTableContext.OptionalModule[Index].Type ==
>FIT_TABLE_TYPE_BIOS_DATA_AREA) ||
>+        (gFitTableContext.OptionalModule[Index].Type ==
>FIT_TABLE_TYPE_CSE_SECURE_BOOT)) {
>+      // NOTE: It might be virtual address now. Just put a place holder.
>+      FitEntryNumber ++;
>+    }
>+  }
>+
>+  return FitEntryNumber;
>+}
>+
>+VOID *
>+FindSpaceSkipApVector (
>+  IN UINT8     *FvBuffer,
>+  IN UINT8     *Address,
>+  IN UINTN     Size
>+  )
>+/*++
>+
>+Routine Description:
>+
>+  No enough space - it might happen that it is occupied by AP wake vector.
>+  Last chance - skip this and search again.
>+
>+Arguments:
>+
>+  FvBuffer       - FvRecovery binary buffer
>+  Address        - Address to be searched from
>+  Size           - Size need to be filled
>+
>+Returns:
>+
>+  FitTableOffset - The FIT table offset
>+  NULL           - No enough space for FIT table
>+
>+*/
>+{
>+  UINT8        *ApVector;
>+  UINT8        *NewAddress;
>+  UINTN        Index;
>+
>+  ApVector = (UINT8 *)((UINTN)Address & ~0xFFF);
>+  if ((UINTN)ApVector <= (UINTN)FvBuffer) {
>+    return NULL;
>+  }
>+
>+  NewAddress = (UINT8 *)(ApVector - Size);
>+  for (Index = 0; Index < Size; Index ++) {
>+    if (NewAddress[Index] != 0xFF) {
>+      return NULL;
>+    }
>+  }
>+  return NewAddress;
>+}
>+
>+VOID *
>+GetFreeSpaceFromFv (
>+  IN UINT8     *FvBuffer,
>+  IN UINT32    FvSize,
>+  IN UINT32    FitEntryNumber
>+  )
>+/*++
>+
>+Routine Description:
>+
>+  Get free space for FIT table from FvRecovery
>+
>+Arguments:
>+
>+  FvBuffer       - FvRecovery binary buffer
>+  FvSize         - FvRecovery size
>+  FitEntryNumber - The FIT entry number
>+
>+Returns:
>+
>+  FitTableOffset - The offset of FIT table in FvRecovery file
>+  NULL           - Free space not found
>+
>+--*/
>+{
>+  UINT8       *FitTableOffset;
>+  INTN        Index;
>+  INTN        SubIndex;
>+  UINT8       *OptionalModuleAddress;
>+  EFI_GUID    VTFGuid = EFI_FFS_VOLUME_TOP_FILE_GUID;
>+  UINT32      AlignedSize;
>+  UINT32      FitTableSize;
>+
>+  EFI_FIRMWARE_VOLUME_HEADER  *FvHeader;
>+  EFI_FFS_FILE_HEADER         *FileHeader;
>+  UINT64                      FvLength;
>+  UINT32                      Offset;
>+  UINT32                      FileLength;
>+  UINT32                      FileOccupiedSize;
>+
>+  //
>+  // Check 4G - FitTablePointerOffset
>+  //
>+  if ((*(UINT64 *)(FvBuffer + FvSize -
>gFitTableContext.FitTablePointerOffset) != 0xFFFFFFFFFFFFFFFFull) &&
>+      (*(UINT64 *)(FvBuffer + FvSize -
>gFitTableContext.FitTablePointerOffset) != 0) &&
>+      (*(UINT64 *)(FvBuffer + FvSize -
>gFitTableContext.FitTablePointerOffset) != 0xEEEEEEEEEEEEEEEEull)) {
>+    Error (NULL, 0, 0, "4G - FitTablePointerOffset is occupied!", NULL);
>+    return NULL;
>+  }
>+  if (gFitTableContext.FitTablePointerOffset2 != 0) {
>+    if ((*(UINT64 *)(FvBuffer + FvSize -
>gFitTableContext.FitTablePointerOffset2) != 0xFFFFFFFFFFFFFFFFull) &&
>+        (*(UINT64 *)(FvBuffer + FvSize -
>gFitTableContext.FitTablePointerOffset2) != 0) &&
>+        (*(UINT64 *)(FvBuffer + FvSize -
>gFitTableContext.FitTablePointerOffset2) != 0xEEEEEEEEEEEEEEEEull)) {
>+      Error (NULL, 0, 0, "4G - FitTablePointerOffset is occupied!", NULL);
>+      return NULL;
>+    }
>+  }
>+
>+  //
>+  // Get EFI_FFS_VOLUME_TOP_FILE_GUID location
>+  //
>+  FitTableOffset = NULL;
>+
>+  FvHeader         = (EFI_FIRMWARE_VOLUME_HEADER *)FvBuffer;
>+  FvLength         = FvHeader->FvLength;
>+  FileHeader       = (EFI_FFS_FILE_HEADER *)(FvBuffer + FvHeader-
>>HeaderLength);
>+  Offset           = (UINTN)FileHeader - (UINTN)FvBuffer;
>+
>+  while (Offset < FvLength) {
>+    FileLength = (*(UINT32 *)(FileHeader->Size)) & 0x00FFFFFF;
>+    FileOccupiedSize = GETOCCUPIEDSIZE(FileLength, 8);
>+    if ((CompareGuid (&(FileHeader->Name), &VTFGuid)) == 0) {
>+      // find it
>+      FitTableOffset = (UINT8 *)FileHeader;
>+      break;
>+    }
>+    FileHeader = (EFI_FFS_FILE_HEADER *)((UINTN)FileHeader +
>FileOccupiedSize);
>+    Offset = (UINTN)FileHeader - (UINTN)FvBuffer;
>+  }
>+
>+  if (FitTableOffset == NULL) {
>+    Error (NULL, 0, 0, "EFI_FFS_VOLUME_TOP_FILE_GUID not found!", NULL);
>+    return NULL;
>+  }
>+
>+  FitTableSize = FitEntryNumber *
>sizeof(FIRMWARE_INTERFACE_TABLE_ENTRY);
>+  FitTableSize += FIT_ALIGNMENT;
>+  FitTableSize &= ~FIT_ALIGNMENT;
>+
>+  FitTableOffset = (UINT8 *)((UINTN)FitTableOffset & ~FIT_ALIGNMENT);
>+  FitTableOffset = (UINT8 *)(FitTableOffset - FitTableSize);
>+
>+  //
>+  // Check it
>+  //
>+  for (Index = 0; Index < (INTN)(FitTableSize); Index ++) {
>+    if (FitTableOffset[Index] != 0xFF) {
>+      //
>+      // No enough space - it might happen that it is occupied by AP wake
>vector.
>+      // Last chance - skip this and search again.
>+      //
>+      FitTableOffset = FindSpaceSkipApVector (FvBuffer,
>&FitTableOffset[Index], FitTableSize);
>+      if (FitTableOffset == NULL) {
>+        Error (NULL, 0, 0, "No enough space for FIT table!", NULL);
>+        return NULL;
>+      }
>+    }
>+  }
>+
>+  //
>+  // Check space for Optional module
>+  //
>+  OptionalModuleAddress = FitTableOffset;
>+  for (Index = 0; Index < (INTN)gFitTableContext.OptionalModuleNumber;
>Index++) {
>+    AlignedSize = gFitTableContext.OptionalModule[Index].Size;
>+    if ((gFitTableContext.OptionalModule[Index].Size & 0x80000000) != 0) {
>+
>+      //
>+      // Need copy binary to file.
>+      //
>+      gFitTableContext.OptionalModule[Index].Size &= ~0x80000000;
>+
>+      AlignedSize = gFitTableContext.OptionalModule[Index].Size;
>+      if ((gFitTableContext.OptionalModule[Index].Type ==
>FIT_TABLE_TYPE_BIOS_POLICY) ||
>+          (gFitTableContext.OptionalModule[Index].Type ==
>FIT_TABLE_TYPE_KEY_MANIFEST) ||
>+          (gFitTableContext.OptionalModule[Index].Type ==
>FIT_TABLE_TYPE_BOOT_POLICY_MANIFEST) ||
>+          (gFitTableContext.OptionalModule[Index].Type ==
>FIT_TABLE_TYPE_BIOS_DATA_AREA) ||
>+          (gFitTableContext.OptionalModule[Index].Type ==
>FIT_TABLE_TYPE_CSE_SECURE_BOOT)) {
>+        // Let it 64 byte align
>+        AlignedSize += BIOS_MODULE_ALIGNMENT;
>+        AlignedSize &= ~BIOS_MODULE_ALIGNMENT;
>+      }
>+
>+      OptionalModuleAddress -= AlignedSize;
>+
>+      if ((gFitTableContext.OptionalModule[Index].Type ==
>FIT_TABLE_TYPE_BIOS_POLICY) ||
>+          (gFitTableContext.OptionalModule[Index].Type ==
>FIT_TABLE_TYPE_KEY_MANIFEST) ||
>+          (gFitTableContext.OptionalModule[Index].Type ==
>FIT_TABLE_TYPE_BOOT_POLICY_MANIFEST) ||
>+          (gFitTableContext.OptionalModule[Index].Type ==
>FIT_TABLE_TYPE_BIOS_DATA_AREA) ||
>+          (gFitTableContext.OptionalModule[Index].Type ==
>FIT_TABLE_TYPE_CSE_SECURE_BOOT)) {
>+        // Let it 64 byte align
>+        OptionalModuleAddress = (UINT8 *)((UINTN)OptionalModuleAddress &
>~BIOS_MODULE_ALIGNMENT);
>+      }
>+
>+      for (SubIndex = 0; SubIndex < (INTN)(AlignedSize); SubIndex ++) {
>+        if (OptionalModuleAddress[SubIndex] != 0xFF) {
>+          //
>+          // No enough space - it might happen that it is occupied by AP wake
>vector.
>+          // Last chance - skip this and search again.
>+          //
>+          OptionalModuleAddress = FindSpaceSkipApVector (FvBuffer,
>&OptionalModuleAddress[SubIndex], AlignedSize);
>+          if (OptionalModuleAddress == NULL) {
>+            Error (NULL, 0, 0, "No enough space for OptionalModule!", NULL);
>+            return NULL;
>+          }
>+        }
>+      }
>+      memcpy (OptionalModuleAddress, (VOID *) (UINTN)
>gFitTableContext.OptionalModule[Index].Address,
>gFitTableContext.OptionalModule[Index].Size);
>+      free ((VOID *) (UINTN)
>gFitTableContext.OptionalModule[Index].Address);
>+      gFitTableContext.OptionalModule[Index].Address = MEMORY_TO_FLASH
>(OptionalModuleAddress, FvBuffer, FvSize);
>+    }
>+    //
>+    // Final: Check BiosPolicyData in BiosModule.
>+    //
>+    if ((gFitTableContext.OptionalModule[Index].Type ==
>FIT_TABLE_TYPE_BIOS_POLICY) ||
>+        (gFitTableContext.OptionalModule[Index].Type ==
>FIT_TABLE_TYPE_KEY_MANIFEST) ||
>+        (gFitTableContext.OptionalModule[Index].Type ==
>FIT_TABLE_TYPE_BOOT_POLICY_MANIFEST) ||
>+        (gFitTableContext.OptionalModule[Index].Type ==
>FIT_TABLE_TYPE_BIOS_DATA_AREA) ||
>+        (gFitTableContext.OptionalModule[Index].Type ==
>FIT_TABLE_TYPE_CSE_SECURE_BOOT)) {
>+      CheckOverlap (gFitTableContext.OptionalModule[Index].Address,
>AlignedSize);
>+    }
>+  }
>+
>+  return FitTableOffset;
>+}
>+
>+VOID
>+PrintFitData (
>+  VOID
>+  )
>+/*++
>+
>+Routine Description:
>+
>+  Output FIT table information
>+
>+Arguments:
>+
>+  None
>+
>+Returns:
>+
>+  None
>+
>+--*/
>+{
>+  UINT32                          Index;
>+
>+  printf ("FIT Table Pointer Offset: 0x%x\n",
>gFitTableContext.FitTablePointerOffset);
>+  if (gFitTableContext.FitTablePointerOffset2 != 0) {
>+    printf ("FIT Table Pointer Offset: 0x%x\n",
>gFitTableContext.FitTablePointerOffset2);
>+  }
>+  printf ("Total FIT Entry number: 0x%x\n",
>gFitTableContext.FitEntryNumber);
>+  printf ("FitHeader version: 0x%04x\n", gFitTableContext.FitHeaderVersion);
>+  if (gFitTableContext.StartupAcm.Address != 0) {
>+    printf ("StartupAcm - (0x%08x, 0x%08x, 0x%04x)\n",
>gFitTableContext.StartupAcm.Address, gFitTableContext.StartupAcm.Size,
>gFitTableContext.StartupAcmVersion);
>+  }
>+  for (Index = 0; Index < gFitTableContext.BiosModuleNumber; Index++) {
>+    printf ("BiosModule[%d] - (0x%08x, 0x%08x, 0x%04x)\n", Index,
>gFitTableContext.BiosModule[Index].Address,
>gFitTableContext.BiosModule[Index].Size,
>gFitTableContext.BiosModuleVersion);
>+  }
>+  for (Index = 0; Index < gFitTableContext.MicrocodeNumber; Index++) {
>+    printf ("Microcode[%d] - (0x%08x, 0x%08x, 0x%04x)\n", Index,
>gFitTableContext.Microcode[Index].Address,
>gFitTableContext.Microcode[Index].Size,
>gFitTableContext.MicrocodeVersion);
>+  }
>+  for (Index = 0; Index < gFitTableContext.OptionalModuleNumber; Index++)
>{
>+    printf ("OptionalModule[%d] - (0x%08x, 0x%08x, 0x%02x, 0x%04x)\n",
>Index, gFitTableContext.OptionalModule[Index].Address,
>gFitTableContext.OptionalModule[Index].Size,
>gFitTableContext.OptionalModule[Index].Type,
>gFitTableContext.OptionalModule[Index].Version);
>+  }
>+  for (Index = 0; Index < gFitTableContext.PortModuleNumber; Index++) {
>+    printf ("PortModule[%d] - (0x%04x, 0x%04x, 0x%02x, 0x%02x, 0x%04x,
>0x%02x, 0x%04x)\n", Index,
>+      (UINT16)gFitTableContext.PortModule[Index].Address,
>(UINT16)(gFitTableContext.PortModule[Index].Address >> 16),
>+      (UINT8)gFitTableContext.PortModule[Index].Size,
>(UINT8)(gFitTableContext.PortModule[Index].Size >> 8),
>(UINT16)(gFitTableContext.PortModule[Index].Size >> 16),
>+      gFitTableContext.PortModule[Index].Type,
>gFitTableContext.PortModule[Index].Version);
>+  }
>+
>+  printf ("\n");
>+  return ;
>+}
>+
>+CHAR8 *mFitTypeStr[] = {
>+  "           ",
>+  "MICROCODE  ",
>+  "STARTUP_ACM",
>+  "           ",
>+  "           ",
>+  "           ",
>+  "           ",
>+  "BIOS_MODULE",
>+  "TPM_POLICY ",
>+  "BIOS_POLICY",
>+  "TXT_POLICY ",
>+  "KEYMANIFEST",
>+  "BP_MANIFEST",
>+  "BIOS_DATA_A",
>+  " ",
>+  " ",
>+  "CSE_SECUREB"
>+};
>+
>+CHAR8  mFitSignature[] = "'_FIT_   ' ";
>+CHAR8  mFitSignatureInHeader[] = "'        ' ";
>+CHAR8 *
>+FitTypeToStr (
>+  IN FIRMWARE_INTERFACE_TABLE_ENTRY  *FitEntry
>+  )
>+/*++
>+
>+Routine Description:
>+
>+  Convert FitEntry type to a string
>+
>+Arguments:
>+
>+  FitEntry - Fit entry
>+
>+Returns:
>+
>+  String
>+
>+--*/
>+{
>+  if (FitEntry->Type == FIT_TABLE_TYPE_HEADER) {
>+    CopyMem (&mFitSignatureInHeader[1], &FitEntry->Address,
>sizeof(FitEntry->Address));
>+    return mFitSignatureInHeader;
>+  }
>+  if (FitEntry->Type < sizeof (mFitTypeStr)/sizeof(mFitTypeStr[0])) {
>+    return mFitTypeStr[FitEntry->Type];
>+  } else {
>+    return "           ";
>+  }
>+}
>+
>+VOID
>+PrintFitTable (
>+  IN UINT8                       *FvBuffer,
>+  IN UINT32                      FvSize
>+  )
>+/*++
>+
>+Routine Description:
>+
>+  Print Fit table in flash image
>+
>+Arguments:
>+
>+  FvBuffer       - FvRecovery binary buffer
>+  FvSize         - FvRecovery size
>+
>+Returns:
>+
>+  None
>+
>+--*/
>+{
>+  FIRMWARE_INTERFACE_TABLE_ENTRY  *FitEntry;
>+  UINT32                          EntryNum;
>+  UINT32                          Index;
>+  UINT32                          FitTableOffset;
>+  FIRMWARE_INTERFACE_TABLE_ENTRY_PORT   *FitEntryPort;
>+
>+  printf ("##############\n");
>+  printf ("# FIT Table: #\n");
>+  printf ("##############\n");
>+
>+  printf ("FIT Pointer Offset: 0x%x\n",
>gFitTableContext.FitTablePointerOffset);
>+  FitTableOffset = *(UINT32 *)(FvBuffer + FvSize -
>gFitTableContext.FitTablePointerOffset);
>+  printf ("FIT Table Address:  0x%x\n", FitTableOffset);
>+  FitEntry = (FIRMWARE_INTERFACE_TABLE_ENTRY
>*)FLASH_TO_MEMORY(FitTableOffset, FvBuffer, FvSize);
>+
>+  //
>+  // Check FitEntry is 16 byte aligned
>+  //
>+  if (((UINTN)FitEntry & 0xF) != 0) {
>+    printf("ERROR: invalid FitEntry address 0x%X!\n", (UINT32) (UINTN)
>FitEntry);
>+    return;
>+  }
>+
>+  EntryNum = *(UINT32 *)(&FitEntry[0].Size[0]) & 0xFFFFFF;
>+  printf ("====== ================ ====== ======== ==============
>==== ======== (====== ==== ====== ==== ======)\n");
>+  printf ("Index:      Address      Size  Version       Type      C_V  Checksum (Index
>Data Width  Bit  Offset)\n");
>+  printf ("====== ================ ====== ======== ==============
>==== ======== (====== ==== ====== ==== ======)\n");
>+  for (Index = 0; Index < EntryNum; Index++) {
>+    printf (" %02d:   %016llx %06x   %04x   %02x-%s  %02x     %02x   ",
>+      Index,
>+      (unsigned long long) FitEntry[Index].Address,
>+      *(UINT32 *)(&FitEntry[Index].Size[0]) & 0xFFFFFF,
>+      FitEntry[Index].Version,
>+      FitEntry[Index].Type,
>+      FitTypeToStr(&FitEntry[Index]),
>+      FitEntry[Index].C_V,
>+      FitEntry[Index].Checksum
>+      );
>+
>+    if (Index == 0) {
>+      if (FitEntry[Index].Type != FIT_TABLE_TYPE_HEADER) {
>+        printf("ERROR: FIT Entry 0 is not Header Type %d!\n",
>FIT_TABLE_TYPE_HEADER);
>+        return;
>+      }
>+      if (strcmp(mFitSignatureInHeader, mFitSignature) != 0) {
>+        printf("ERROR: FIT Entry 0 signature invalid (%s, expected %s)!\n",
>mFitSignatureInHeader, mFitSignature);
>+        return;
>+      }
>+
>+    }
>+
>+    switch (FitEntry[Index].Type) {
>+    case FIT_TABLE_TYPE_TPM_POLICY:
>+    case FIT_TABLE_TYPE_TXT_POLICY:
>+      if (FitEntry[Index].Version == 0) {
>+        FitEntryPort = (FIRMWARE_INTERFACE_TABLE_ENTRY_PORT
>*)&FitEntry[Index];
>+        printf (" ( %04x  %04x   %02x    %02x   %04x )\n",
>+          FitEntryPort->IndexPort,
>+          FitEntryPort->DataPort,
>+          FitEntryPort->Width,
>+          FitEntryPort->Bit,
>+          FitEntryPort->Index
>+          );
>+        break;
>+      }
>+      // Not Port Configure, pass through
>+    default:
>+      printf ("\n");
>+      break;
>+    }
>+  }
>+  printf ("====== ================ ====== ======== ==============
>==== ======== (====== ==== ====== ==== ======)\n");
>+  printf ("Index:      Address      Size  Version       Type      C_V  Checksum (Index
>Data Width  Bit  Offset)\n");
>+  printf ("====== ================ ====== ======== ==============
>==== ======== (====== ==== ====== ==== ======)\n");
>+}
>+
>+/**
>+
>+  This function dump raw data.
>+
>+  @param  Data  raw data
>+  @param  Size  raw data size
>+
>+**/
>+VOID
>+DumpData (
>+  IN UINT8  *Data,
>+  IN UINT32 Size
>+  )
>+{
>+  UINT32 Index;
>+  for (Index = 0; Index < Size; Index++) {
>+    printf ("%02x", Data[Index]);
>+  }
>+}
>+
>+/**
>+
>+  This function dump raw data with colume format.
>+
>+  @param  Data  raw data
>+  @param  Size  raw data size
>+
>+**/
>+VOID
>+DumpHex (
>+  IN UINT8  *Data,
>+  IN UINT32 Size
>+  )
>+{
>+  UINT32  Index;
>+  UINT32  Count;
>+  UINT32  Left;
>+
>+#define COLUME_SIZE  (16 * 2)
>+
>+  Count = Size / COLUME_SIZE;
>+  Left  = Size % COLUME_SIZE;
>+  for (Index = 0; Index < Count; Index++) {
>+    printf ("%04x: ", Index * COLUME_SIZE);
>+    DumpData (Data + Index * COLUME_SIZE, COLUME_SIZE);
>+    printf ("\n");
>+  }
>+
>+  if (Left != 0) {
>+    printf ("%04x: ", Index * COLUME_SIZE);
>+    DumpData (Data + Index * COLUME_SIZE, Left);
>+    printf ("\n");
>+  }
>+}
>+
>+//
>+// This table defines the ACM type string
>+//
>+CHAR8 *mAcmTypeStr[] = {
>+  "BIOS ACM",
>+  "SINIT ACM",
>+};
>+
>+//
>+// This table defines the ACM capability string
>+//
>+CHAR8 *mCapabilityStr[] = {
>+  "GETSEC[WAKEUP] for RLP   ",
>+  "MONITOR address for RLP  ",
>+  "ECX for MLE PageTable    ",
>+  "STM support              ",
>+};
>+
>+VOID
>+DumpAcm (
>+  IN ACM_FORMAT                    *Acm
>+  )
>+/*++
>+
>+Routine Description:
>+
>+  DumpAcm information
>+
>+Arguments:
>+
>+  Acm       - ACM buffer
>+
>+Returns:
>+
>+  None
>+
>+--*/
>+{
>+  CHIPSET_ACM_INFORMATION_TABLE *ChipsetAcmInformationTable;
>+  CHIPSET_ID_LIST               *ChipsetIdList;
>+  PROCESSOR_ID_LIST             *ProcessorIdList;
>+  UINT32                        Index;
>+  UINT8                         *Buffer;
>+
>+  printf (
>+
>"**********************************************************
>*******************\n"
>+    "*         ACM                                                               *\n"
>+
>"**********************************************************
>*******************\n"
>+    );
>+
>+  printf ("ACM: (%08x)\n", (UINT32) (UINTN) Acm);
>+  printf ("  ModuleType                 - %04x\n", Acm->ModuleType);
>+  if (Acm->ModuleType == ACM_MODULE_TYPE_CHIPSET_ACM) {
>+    printf ("    Chipset ACM\n");
>+  }
>+  printf ("  ModuleSubType              - %04x\n", Acm->ModuleSubType);
>+  if ((Acm->ModuleSubType &
>ACM_MODULE_SUBTYPE_CAPABLE_OF_EXECUTE_AT_RESET) != 0) {
>+    printf ("    Capable of be Executed at Reset\n");
>+  }
>+  if ((Acm->ModuleSubType & ACM_MODULE_SUBTYPE_ANC_MODULE) != 0)
>{
>+    printf ("    AnC Module\n");
>+  }
>+  printf ("  HeaderLen                  - %08x\n", Acm->HeaderLen);
>+  printf ("  HeaderVersion              - %08x\n", Acm->HeaderVersion);
>+  printf ("  ChipsetID                  - %04x\n", Acm->ChipsetID);
>+  printf ("  Flags                      - %04x\n", Acm->Flags);
>+  printf ("    PreProduction            - %04x\n", Acm->Flags &
>ACM_MODULE_FLAG_PREPRODUCTION);
>+  printf ("    Debug Signed             - %04x\n", Acm->Flags &
>ACM_MODULE_FLAG_DEBUG_SIGN);
>+  printf ("  ModuleVendor               - %08x\n", Acm->ModuleVendor);
>+  printf ("  Date                       - %08x\n", Acm->Date);
>+  printf ("  Size                       - %08x\n", Acm->Size);
>+  printf ("  TxtSvn                     - %04x\n", Acm->TxtSvn);
>+  printf ("  SeSvn                      - %04x\n", Acm->SeSvn);
>+  printf ("  CodeControl                - %08x\n", Acm->CodeControl);
>+  printf ("  ErrorEntryPoint            - %08x\n", Acm->ErrorEntryPoint);
>+  printf ("  GDTLimit                   - %08x\n", Acm->GDTLimit);
>+  printf ("  GDTBasePtr                 - %08x\n", Acm->GDTBasePtr);
>+  printf ("  SegSel                     - %08x\n", Acm->SegSel);
>+  printf ("  EntryPoint                 - %08x\n", Acm->EntryPoint);
>+  printf ("  KeySize                    - %08x\n", Acm->KeySize);
>+  printf ("  ScratchSize                - %08x\n", Acm->ScratchSize);
>+
>+  Buffer = (UINT8 *)(Acm + 1);
>+  printf ("  RSAPubKey                  - \n");
>+  DumpHex (Buffer, Acm->KeySize * 4);
>+  printf ("\n");
>+  Buffer += Acm->KeySize * 4;
>+
>+  if (Acm->HeaderVersion == ACM_HEADER_VERSION_3) {
>+    printf ("  RSASig                     - \n");
>+    DumpHex (Buffer, ACM_PKCS_1_5_RSA_SIGNATURE_SHA384_SIZE); //
>PKCS #1.5 RSA Signature
>+    printf ("\n");
>+    Buffer += ACM_PKCS_1_5_RSA_SIGNATURE_SHA384_SIZE;
>+  } else {
>+    printf ("  RSAPubExp                  - %08x\n", *(UINT32 *)Buffer);
>+    Buffer += 4;
>+
>+    printf ("  RSASig                     - \n");
>+    DumpHex (Buffer, ACM_PKCS_1_5_RSA_SIGNATURE_SHA256_SIZE); //
>PKCS #1.5 RSA Signature
>+    printf ("\n");
>+    Buffer += ACM_PKCS_1_5_RSA_SIGNATURE_SHA256_SIZE;
>+  }
>+  Buffer += Acm->ScratchSize * 4;
>+
>+  if ((Acm->ModuleSubType & ACM_MODULE_SUBTYPE_ANC_MODULE) ==
>0) {
>+    ChipsetAcmInformationTable = (CHIPSET_ACM_INFORMATION_TABLE
>*)Buffer;
>+    printf ("Chipset ACM info:\n");
>+    printf (
>+      "  Guid                       - {%08x-%08x-%08x-%08x}\n",
>+      ChipsetAcmInformationTable->Guid.Guid0,
>+      ChipsetAcmInformationTable->Guid.Guid1,
>+      ChipsetAcmInformationTable->Guid.Guid2,
>+      ChipsetAcmInformationTable->Guid.Guid3
>+      );
>+    printf ("  ChipsetACMType             - %02x\n", ChipsetAcmInformationTable-
>>ChipsetACMType);
>+    if (ChipsetAcmInformationTable->ChipsetACMType <
>sizeof(mAcmTypeStr)/sizeof(mAcmTypeStr[0])) {
>+      printf ("    %s\n", mAcmTypeStr[ChipsetAcmInformationTable-
>>ChipsetACMType]);
>+    }
>+    printf ("  Version                    - %02x\n", ChipsetAcmInformationTable-
>>Version);
>+    printf ("  Length                     - %04x\n", ChipsetAcmInformationTable-
>>Length);
>+    printf ("  ChipsetIDList              - %08x\n", ChipsetAcmInformationTable-
>>ChipsetIDList);
>+    printf ("  OsSinitTableVer            - %08x\n", ChipsetAcmInformationTable-
>>OsSinitTableVer);
>+    printf ("  MinMleHeaderVer            - %08x\n", ChipsetAcmInformationTable-
>>MinMleHeaderVer);
>+    if (ChipsetAcmInformationTable->Version >=
>CHIPSET_ACM_INFORMATION_TABLE_VERSION_3) {
>+      printf ("  Capabilities               - %08x\n", ChipsetAcmInformationTable-
>>Capabilities);
>+      for (Index = 0; Index < sizeof(mCapabilityStr)/sizeof(mCapabilityStr[0]);
>Index++) {
>+        if (mCapabilityStr[Index] == NULL) {
>+          continue;
>+        }
>+        printf (
>+          "    %s- %08x\n",
>+          mCapabilityStr[Index],
>+          (ChipsetAcmInformationTable->Capabilities & (1 << Index))
>+          );
>+      }
>+      printf ("  AcmVersion                 - %02x\n", ChipsetAcmInformationTable-
>>AcmVersion);
>+      printf ("  AcmRevision                - %02x.%02x.%02x\n",
>ChipsetAcmInformationTable->AcmRevision[0],
>ChipsetAcmInformationTable->AcmRevision[1],
>ChipsetAcmInformationTable->AcmRevision[2]);
>+    }
>+    if (ChipsetAcmInformationTable->Version >=
>CHIPSET_ACM_INFORMATION_TABLE_VERSION_4) {
>+      printf ("  ProcessorIDList            - %08x\n", ChipsetAcmInformationTable-
>>ProcessorIDList);
>+    }
>+
>+    ChipsetIdList = (CHIPSET_ID_LIST *)((UINTN)Acm +
>ChipsetAcmInformationTable->ChipsetIDList);
>+    printf ("Chipset ID List info:\n");
>+    printf ("  Count                      - %08x\n", ChipsetIdList->Count);
>+    for (Index = 0; Index < ChipsetIdList->Count; Index++) {
>+      printf ("  ID[%d]:\n", Index);
>+      printf ("    Flags                    - %08x\n", ChipsetIdList-
>>ChipsetID[Index].Flags);
>+      printf ("      RevisionIdMask         - %08x\n", ChipsetIdList-
>>ChipsetID[Index].Flags & ACM_CHIPSET_ID_REVISION_ID_MAKE);
>+      printf ("    VendorID                 - %04x\n", ChipsetIdList-
>>ChipsetID[Index].VendorID);
>+      printf ("    DeviceID                 - %04x\n", ChipsetIdList-
>>ChipsetID[Index].DeviceID);
>+      printf ("    RevisionID               - %04x\n", ChipsetIdList-
>>ChipsetID[Index].RevisionID);
>+    }
>+    if (ChipsetAcmInformationTable->Version <
>CHIPSET_ACM_INFORMATION_TABLE_VERSION_4) {
>+      goto End;
>+    }
>+    ProcessorIdList = (PROCESSOR_ID_LIST *)((UINTN)Acm +
>ChipsetAcmInformationTable->ProcessorIDList);
>+    printf ("Processor ID List info:\n");
>+    printf ("  Count                      - %08x\n", ProcessorIdList->Count);
>+    for (Index = 0; Index < ProcessorIdList->Count; Index++) {
>+      printf ("  ID[%d]:\n", Index);
>+      printf ("    FMS                      - %08x\n", ProcessorIdList-
>>ProcessorID[Index].FMS);
>+      printf ("    FMSMask                  - %08x\n", ProcessorIdList-
>>ProcessorID[Index].FMSMask);
>+      printf ("    PlatformID               - %016llx\n", (unsigned long long)
>ProcessorIdList->ProcessorID[Index].PlatformID);
>+      printf ("    PlatformMask             - %016llx\n", (unsigned long long)
>ProcessorIdList->ProcessorID[Index].PlatformMask);
>+    }
>+  }
>+
>+End:
>+  printf (
>+
>"**********************************************************
>*******************\n\n"
>+    );
>+}
>+
>+BOOLEAN
>+CheckAcm (
>+  IN ACM_FORMAT                        *Acm,
>+  IN UINTN                             AcmMaxSize
>+  )
>+/*++
>+
>+Routine Description:
>+
>+  Check Acm information
>+
>+Arguments:
>+
>+  Acm        - ACM buffer
>+  AcmMaxSize - ACM max size
>+
>+Returns:
>+
>+  TRUE  - ACM is valid
>+  FALSE - ACM is invalid
>+
>+--*/
>+{
>+  CHIPSET_ACM_INFORMATION_TABLE *ChipsetAcmInformationTable;
>+  CHIPSET_ID_LIST               *ChipsetIdList;
>+  PROCESSOR_ID_LIST             *ProcessorIdList;
>+  UINT8                         *Buffer;
>+
>+  if (Acm->ModuleType != ACM_MODULE_TYPE_CHIPSET_ACM) {
>+    printf ("ACM invalid : ModuleType!\n");
>+    return FALSE;
>+  }
>+  if (Acm->Size * 4 > AcmMaxSize) {
>+    printf ("ACM invalid : Size!\n");
>+    return FALSE;
>+  }
>+
>+  Buffer = (UINT8 *)(Acm + 1);
>+  Buffer += Acm->KeySize * 4;
>+  if (Acm->HeaderVersion == ACM_HEADER_VERSION_3) {
>+    Buffer += ACM_PKCS_1_5_RSA_SIGNATURE_SHA384_SIZE;
>+  } else {
>+    Buffer += 4;
>+    Buffer += ACM_PKCS_1_5_RSA_SIGNATURE_SHA256_SIZE;
>+  }
>+  Buffer += Acm->ScratchSize * 4;
>+
>+  if ((Acm->ModuleSubType & ACM_MODULE_SUBTYPE_ANC_MODULE) ==
>0) {
>+    ChipsetAcmInformationTable = (CHIPSET_ACM_INFORMATION_TABLE
>*)Buffer;
>+    if ((UINTN)ChipsetAcmInformationTable >= (UINTN)Acm + AcmMaxSize) {
>+      printf ("ACM invalid : ChipsetAcmInformationTable!\n");
>+      return FALSE;
>+    }
>+
>+    if (CompareGuid ((EFI_GUID *)&ChipsetAcmInformationTable->Guid,
>(EFI_GUID *)&mChipsetAcmInformationTableGuid03) != 0) {
>+      printf ("ACM invalid : ChipsetACMGuid!\n");
>+      return FALSE;
>+    }
>+    if (ChipsetAcmInformationTable->ChipsetACMType !=
>CHIPSET_ACM_TYPE_BIOS) {
>+      printf ("ACM invalid : ChipsetACMType!\n");
>+      return FALSE;
>+    }
>+    if (ChipsetAcmInformationTable->Version <
>CHIPSET_ACM_INFORMATION_TABLE_VERSION_3) {
>+      printf ("ACM invalid : ChipsetACMVersion!\n");
>+      return FALSE;
>+    }
>+    if ((UINTN)ChipsetAcmInformationTable + ChipsetAcmInformationTable-
>>Length > (UINTN)Acm + AcmMaxSize) {
>+      printf ("ACM invalid : ChipsetACMLength!\n");
>+      return FALSE;
>+    }
>+
>+    if (ChipsetAcmInformationTable->ChipsetIDList >= AcmMaxSize) {
>+      printf ("ACM invalid : ChipsetACMChipsetIDList!\n");
>+      return FALSE;
>+    }
>+    ChipsetIdList = (CHIPSET_ID_LIST *)((UINTN)Acm +
>ChipsetAcmInformationTable->ChipsetIDList);
>+    if (ChipsetIdList->Count == 0) {
>+      printf ("ACM invalid : ChipsetACMChipsetIDListCount!\n");
>+      return FALSE;
>+    }
>+    if (ChipsetAcmInformationTable->ChipsetIDList + sizeof(CHIPSET_ID_LIST)
>+ (ChipsetIdList->Count - 1) * sizeof(ACM_CHIPSET_ID) > AcmMaxSize) {
>+      printf ("ACM invalid : ChipsetACMChipsetIDList!\n");
>+      return FALSE;
>+    }
>+
>+    if (ChipsetAcmInformationTable->Version <
>CHIPSET_ACM_INFORMATION_TABLE_VERSION_4) {
>+      goto End;
>+    }
>+
>+    if (ChipsetAcmInformationTable->ProcessorIDList >= AcmMaxSize) {
>+      printf ("ACM invalid : ChipsetACMProcessorIDList!\n");
>+      return FALSE;
>+    }
>+    ProcessorIdList = (PROCESSOR_ID_LIST *)((UINTN)Acm +
>ChipsetAcmInformationTable->ProcessorIDList);
>+    if (ProcessorIdList->Count == 0) {
>+      printf ("ACM invalid : ChipsetACMProcessorIdListCount!\n");
>+      return FALSE;
>+    }
>+    if (ChipsetAcmInformationTable->ChipsetIDList +
>sizeof(PROCESSOR_ID_LIST) + (ChipsetIdList->Count - 1) *
>sizeof(ACM_PROCESSOR_ID) > AcmMaxSize) {
>+      printf ("ACM invalid : ChipsetACMProcessorIdList!\n");
>+      return FALSE;
>+    }
>+  }
>+
>+End:
>+
>+  return TRUE;
>+}
>+
>+VOID
>+FillFitTable (
>+  IN UINT8     *FvBuffer,
>+  IN UINT32    FvSize,
>+  IN UINT8     *FitTableOffset
>+  )
>+/*++
>+
>+Routine Description:
>+
>+  Fill the FIT table information to FvRecovery
>+
>+Arguments:
>+
>+  FvBuffer       - FvRecovery binary buffer
>+  FvSize         - FvRecovery size
>+  FitTableOffset - The offset of FIT table in FvRecovery file
>+
>+Returns:
>+
>+  None
>+
>+--*/
>+{
>+  FIRMWARE_INTERFACE_TABLE_ENTRY *FitEntry;
>+  UINT32                          FitIndex;
>+  UINT32                          Index;
>+  UINT8                           Checksum;
>+  UINTN                           SubIndex;
>+  FIT_TABLE_CONTEXT_ENTRY         TempContextEntry;
>+  FIRMWARE_INTERFACE_TABLE_ENTRY  TempTableEntry;
>+
>+  //
>+  // 1. FitPointer
>+  //
>+  *(UINT64 *)(FvBuffer + FvSize - gFitTableContext.FitTablePointerOffset) =
>(UINT64)(UINTN)MEMORY_TO_FLASH (FitTableOffset, FvBuffer, FvSize);
>+  if (gFitTableContext.FitTablePointerOffset2 != 0) {
>+    *(UINT64 *)(FvBuffer + FvSize - gFitTableContext.FitTablePointerOffset2)
>= (UINT64)(UINTN)MEMORY_TO_FLASH (FitTableOffset, FvBuffer, FvSize);
>+  }
>+
>+  FitEntry = (FIRMWARE_INTERFACE_TABLE_ENTRY *)FitTableOffset;
>+  FitIndex = 0;
>+
>+  //
>+  // 2. FitHeader
>+  //
>+  FitEntry[FitIndex].Address             = *(UINT64 *)"_FIT_   ";
>+  *(UINT32 *)&FitEntry[FitIndex].Size[0] = gFitTableContext.FitEntryNumber;
>+  FitEntry[FitIndex].Version             =
>(UINT16)gFitTableContext.FitHeaderVersion;
>+  FitEntry[FitIndex].Type                = FIT_TABLE_TYPE_HEADER;
>+  FitEntry[FitIndex].C_V                 = 1;
>+  //
>+  // Checksum will be updated later...
>+  //
>+  FitEntry[FitIndex].Checksum            = 0;
>+
>+  //
>+  // 3. Microcode
>+  //
>+  FitIndex++;
>+  for (Index = 0; Index < gFitTableContext.MicrocodeNumber; Index++) {
>+    FitEntry[FitIndex].Address             =
>gFitTableContext.Microcode[Index].Address;
>+    *(UINT32 *)&FitEntry[FitIndex].Size[0] = 0;
>//gFitTableContext.Microcode[Index].Size / 16;
>+    FitEntry[FitIndex].Version             =
>(UINT16)gFitTableContext.MicrocodeVersion;
>+    FitEntry[FitIndex].Type                = FIT_TABLE_TYPE_MICROCODE;
>+    FitEntry[FitIndex].C_V                 = 0;
>+    FitEntry[FitIndex].Checksum            = 0;
>+    FitIndex++;
>+  }
>+
>+  //
>+  // 4. StartupAcm
>+  //
>+  if (gFitTableContext.StartupAcm.Address != 0) {
>+    FitEntry[FitIndex].Address             = gFitTableContext.StartupAcm.Address;
>+    *(UINT32 *)&FitEntry[FitIndex].Size[0] = 0;
>//gFitTableContext.StartupAcm.Size / 16;
>+    FitEntry[FitIndex].Version             =
>(UINT16)gFitTableContext.StartupAcmVersion;
>+    FitEntry[FitIndex].Type                = FIT_TABLE_TYPE_STARTUP_ACM;
>+    FitEntry[FitIndex].C_V                 = 0;
>+    FitEntry[FitIndex].Checksum            = 0;
>+    FitIndex++;
>+  }
>+
>+  //
>+  // 5. BiosModule
>+  //
>+  //
>+  // BiosModule segments order needs to be put from low addresss to high
>for Btg requirement
>+  //
>+  if (gFitTableContext.BiosModuleNumber > 1) {
>+    for (Index = 0; Index < (UINTN)gFitTableContext.BiosModuleNumber - 1;
>Index++){
>+      for (SubIndex = 0; SubIndex < gFitTableContext.BiosModuleNumber -
>Index - 1; SubIndex++) {
>+        if (gFitTableContext.BiosModule[SubIndex].Address >
>gFitTableContext.BiosModule[SubIndex + 1].Address) {
>+          CopyMem (&TempContextEntry,
>&gFitTableContext.BiosModule[SubIndex],
>sizeof(FIT_TABLE_CONTEXT_ENTRY));
>+          CopyMem (&gFitTableContext.BiosModule[SubIndex],
>&gFitTableContext.BiosModule[SubIndex + 1],
>sizeof(FIT_TABLE_CONTEXT_ENTRY));
>+          CopyMem (&gFitTableContext.BiosModule[SubIndex + 1],
>&TempContextEntry, sizeof(FIT_TABLE_CONTEXT_ENTRY));
>+        }
>+      }
>+    }
>+  }
>+  for (Index = 0; Index < gFitTableContext.BiosModuleNumber; Index++) {
>+    FitEntry[FitIndex].Address             =
>gFitTableContext.BiosModule[Index].Address;
>+    *(UINT32 *)&FitEntry[FitIndex].Size[0] =
>gFitTableContext.BiosModule[Index].Size / 16;
>+    FitEntry[FitIndex].Version             =
>(UINT16)gFitTableContext.BiosModuleVersion;
>+    FitEntry[FitIndex].Type                = FIT_TABLE_TYPE_BIOS_MODULE;
>+    FitEntry[FitIndex].C_V                 = 0;
>+    FitEntry[FitIndex].Checksum            = 0;
>+    FitIndex++;
>+  }
>+
>+  //
>+  // 6. Optional module
>+  //
>+  for (Index = 0; Index < gFitTableContext.OptionalModuleNumber; Index++)
>{
>+    FitEntry[FitIndex].Address             =
>gFitTableContext.OptionalModule[Index].Address;
>+    *(UINT32 *)&FitEntry[FitIndex].Size[0] =
>gFitTableContext.OptionalModule[Index].Size;
>+    FitEntry[FitIndex].Version             =
>(UINT16)gFitTableContext.OptionalModule[Index].Version;
>+    FitEntry[FitIndex].Type                =
>(UINT8)gFitTableContext.OptionalModule[Index].Type;
>+    FitEntry[FitIndex].C_V                 = 0;
>+    FitEntry[FitIndex].Checksum            = 0;
>+    FitIndex++;
>+  }
>+
>+  //
>+  // 7. Port module
>+  //
>+  for (Index = 0; Index < gFitTableContext.PortModuleNumber; Index++) {
>+    FitEntry[FitIndex].Address             =
>gFitTableContext.PortModule[Index].Address +
>((UINT64)gFitTableContext.PortModule[Index].Size << 32);
>+    *(UINT32 *)&FitEntry[FitIndex].Size[0] = 0;
>+    FitEntry[FitIndex].Version             =
>(UINT16)gFitTableContext.PortModule[Index].Version;
>+    FitEntry[FitIndex].Type                =
>(UINT8)gFitTableContext.PortModule[Index].Type;
>+    FitEntry[FitIndex].C_V                 = 0;
>+    FitEntry[FitIndex].Checksum            = 0;
>+    FitIndex++;
>+  }
>+
>+  //
>+  // The FIT records must always be arranged in the ascending order of their
>type attribute in the FIT.
>+  //
>+  for (Index = 0; Index < (UINTN)FitIndex - 1; Index++){
>+    for (SubIndex = 0; SubIndex < FitIndex - Index - 1; SubIndex++) {
>+      if (FitEntry[SubIndex].Type > FitEntry[SubIndex + 1].Type) {
>+        CopyMem (&TempTableEntry, &FitEntry[SubIndex],
>sizeof(FIRMWARE_INTERFACE_TABLE_ENTRY));
>+        CopyMem (&FitEntry[SubIndex], &FitEntry[SubIndex + 1],
>sizeof(FIRMWARE_INTERFACE_TABLE_ENTRY));
>+        CopyMem (&FitEntry[SubIndex + 1], &TempTableEntry,
>sizeof(FIRMWARE_INTERFACE_TABLE_ENTRY));
>+      }
>+    }
>+  }
>+
>+  //
>+  // Update FIT header signature as final step
>+  //
>+  Checksum = CalculateChecksum8 ((UINT8 *)&FitEntry[0], sizeof
>(FIRMWARE_INTERFACE_TABLE_ENTRY) * FitIndex);
>+  FitEntry[0].Checksum = Checksum;
>+}
>+
>+VOID
>+ClearFitTable (
>+  IN UINT8     *FvBuffer,
>+  IN UINT32    FvSize
>+  )
>+/*++
>+
>+Routine Description:
>+
>+  Clear the FIT table information to Fvrecovery
>+
>+Arguments:
>+
>+  FvBuffer       - Fvrecovery binary buffer
>+  FvSize         - Fvrecovery size
>+
>+Returns:
>+
>+  None
>+
>+--*/
>+{
>+  FIRMWARE_INTERFACE_TABLE_ENTRY *FitEntry;
>+  UINT32                          EntryNum;
>+  UINT32                          FitIndex;
>+  UINT64                          FitTablePointer;
>+  UINT8                           *Buffer;
>+  UINT32                          BufferSize;
>+
>+  FitTablePointer = *(UINT64 *)(FvBuffer + FvSize -
>gFitTableContext.FitTablePointerOffset);
>+  FitEntry = (FIRMWARE_INTERFACE_TABLE_ENTRY *)FLASH_TO_MEMORY
>(FitTablePointer, FvBuffer, FvSize);
>+
>+  //
>+  // Clear FIT pointer
>+  //
>+  *(UINT64 *)(FvBuffer + FvSize - gFitTableContext.FitTablePointerOffset) =
>0xEEEEEEEEEEEEEEEEull;
>+  if (gFitTableContext.FitTablePointerOffset2 != 0) {
>+    *(UINT64 *)(FvBuffer + FvSize - gFitTableContext.FitTablePointerOffset2)
>= 0xEEEEEEEEEEEEEEEEull;
>+  }
>+
>+  //
>+  // Clear FIT table
>+  //
>+  EntryNum = *(UINT32 *)(&FitEntry[0].Size[0]) & 0xFFFFFF;
>+  for (FitIndex = 0; FitIndex < EntryNum; FitIndex++) {
>+    switch (FitEntry[FitIndex].Type) {
>+    case FIT_TABLE_TYPE_BIOS_POLICY:
>+    case FIT_TABLE_TYPE_KEY_MANIFEST:
>+    case FIT_TABLE_TYPE_BOOT_POLICY_MANIFEST:
>+    case FIT_TABLE_TYPE_BIOS_DATA_AREA:
>+    case FIT_TABLE_TYPE_CSE_SECURE_BOOT:
>+      //
>+      // Clear FIT table data buffer
>+      //
>+      Buffer = FLASH_TO_MEMORY (FitEntry[FitIndex].Address, FvBuffer,
>FvSize);
>+      BufferSize = (*(UINT32 *)FitEntry[FitIndex].Size) & 0xFFFFFF;
>+      SetMem (Buffer, BufferSize, 0xFF);
>+      break;
>+    default:
>+      break;
>+    }
>+    //
>+    // Clear FIT table itself
>+    //
>+    SetMem (&FitEntry[FitIndex], sizeof(FitEntry[FitIndex]), 0xFF);
>+  }
>+}
>+
>+STATUS
>+WriteOutputFile (
>+  IN CHAR8   *FileName,
>+  IN UINT8   *FileData,
>+  IN UINT32  FileSize
>+  )
>+/*++
>+
>+Routine Description:
>+
>+  Read input file
>+
>+Arguments:
>+
>+  FileName      - The input file name
>+  FileData      - The input file data
>+  FileSize      - The input file size
>+
>+Returns:
>+
>+  STATUS_SUCCESS - Write file data successfully
>+  STATUS_ERROR   - The file data is not written
>+
>+--*/
>+{
>+  FILE                        *FpOut;
>+
>+  //
>+  // Open the output FvRecovery.fv file
>+  //
>+  if ((FpOut = fopen (FileName, "w+b")) == NULL) {
>+    Error (NULL, 0, 0, "Unable to open file", "%s", FileName);
>+    return STATUS_ERROR;
>+  }
>+  //
>+  // Write the output FvRecovery.fv file
>+  //
>+  if ((fwrite (FileData, 1, FileSize, FpOut)) != FileSize) {
>+    Error (NULL, 0, 0, "Write output file error!", NULL);
>+    fclose (FpOut);
>+    return STATUS_ERROR;
>+  }
>+
>+  //
>+  // Close the output FvRecovery.fv file
>+  //
>+  fclose (FpOut);
>+
>+  return STATUS_SUCCESS;
>+}
>+
>+UINT32
>+GetFvRecoveryInfoFromFd (
>+  IN UINT8                       *FdBuffer,
>+  IN UINT32                      FdFileSize,
>+  OUT UINT8                      **FvRecovery
>+  )
>+/*++
>+
>+Routine Description:
>+
>+  Get FvRecovery information from Fd file.
>+
>+Arguments:
>+
>+  FdBuffer     - Fd file buffer.
>+  FdFileSize   - Fd file size.
>+  FvRecovery   - FvRecovery pointer in Fd file buffer
>+
>+Returns:
>+  FvRecovery file size
>+
>+--*/
>+{
>+  UINT8                         *FileBuffer = NULL;
>+  UINT32                        FvRecoveryFileSize =0;
>+  EFI_GUID                      VTFGuid = EFI_FFS_VOLUME_TOP_FILE_GUID;
>+  UINT32                        FvLength;
>+  UINT32                        FileLength;
>+
>+  *FvRecovery = NULL;
>+  FileBuffer = FindNextFvHeader (FdBuffer, FdFileSize);
>+  if (FileBuffer == NULL) {
>+    return 0;
>+  }
>+
>+  while ((UINTN)FileBuffer < (UINTN)FdBuffer + FdFileSize) {
>+    FvLength         = (UINT32)((EFI_FIRMWARE_VOLUME_HEADER
>*)FileBuffer)->FvLength;
>+
>+    if (FindFileFromFvByGuid (FileBuffer, FvLength, &VTFGuid, &FileLength) !=
>NULL) {
>+      //
>+      // Found the VTF
>+      //
>+      FvRecoveryFileSize = FvLength;
>+      *FvRecovery = FileBuffer;
>+    }
>+
>+    //
>+    // Next fv
>+    //
>+    FileBuffer = (UINT8 *)FileBuffer + FvLength;
>+    if ((UINTN)FileBuffer >= (UINTN)FdBuffer + FdFileSize) {
>+      break;
>+    }
>+    FileBuffer = FindNextFvHeader (FileBuffer, (UINTN)FdBuffer + FdFileSize -
>(UINTN)FileBuffer);
>+    if (FileBuffer == NULL) {
>+      break;
>+    }
>+
>+  }
>+
>+  //
>+  // Return
>+  //
>+  return FvRecoveryFileSize;
>+}
>+
>+UINT32
>+GetFitEntryInfo (
>+  IN UINT8     *FvBuffer,
>+  IN UINT32    FvSize
>+  )
>+/*++
>+
>+Routine Description:
>+
>+  Fill the FIT table information to Fvrecovery
>+
>+Arguments:
>+
>+  FvBuffer       - Fvrecovery binary buffer
>+  FvSize         - Fvrecovery size
>+
>+Returns:
>+
>+  0 - Fit Table not found
>+
>+--*/
>+{
>+  FIRMWARE_INTERFACE_TABLE_ENTRY *FitEntry;
>+  UINT32                          FitIndex;
>+  UINT32                          FitTableOffset;
>+
>+  //
>+  // 1. FitPointer
>+  //
>+  if (gFitTableContext.FitTablePointerOffset == 0) {
>+    gFitTableContext.FitTablePointerOffset =
>DEFAULT_FIT_TABLE_POINTER_OFFSET;
>+  }
>+  gFitTableContext.FitTablePointerOffset2 = 0;
>+
>+  FitTableOffset = *(UINT32 *)(FvBuffer + FvSize -
>gFitTableContext.FitTablePointerOffset);
>+
>+  FitEntry = (FIRMWARE_INTERFACE_TABLE_ENTRY
>*)FLASH_TO_MEMORY(FitTableOffset, FvBuffer, FvSize);
>+  FitIndex = 0;
>+
>+  //
>+  // 2. FitHeader
>+  //
>+  if (FitEntry[FitIndex].Address != *(UINT64 *)"_FIT_   ") {
>+    return 0;
>+  }
>+  if (FitEntry[FitIndex].Type != FIT_TABLE_TYPE_HEADER) {
>+    return 0;
>+  }
>+  gFitTableContext.FitEntryNumber = *(UINT32 *)&FitEntry[FitIndex].Size[0];
>+  gFitTableContext.FitHeaderVersion = FitEntry[FitIndex].Version;
>+
>+  //
>+  // 3. FitEntry
>+  //
>+  FitIndex++;
>+  for (; FitIndex < gFitTableContext.FitEntryNumber; FitIndex++) {
>+    switch (FitEntry[FitIndex].Type) {
>+    case FIT_TABLE_TYPE_MICROCODE:
>+
>gFitTableContext.Microcode[gFitTableContext.MicrocodeNumber].Address =
>(UINT32)FitEntry[FitIndex].Address;
>+      gFitTableContext.MicrocodeVersion                                    =
>FitEntry[FitIndex].Version;
>+      gFitTableContext.MicrocodeNumber ++;
>+      break;
>+    case FIT_TABLE_TYPE_STARTUP_ACM:
>+      gFitTableContext.StartupAcm.Address =
>(UINT32)FitEntry[FitIndex].Address;
>+      gFitTableContext.StartupAcmVersion  = FitEntry[FitIndex].Version;
>+      break;
>+    case FIT_TABLE_TYPE_BIOS_MODULE:
>+
>gFitTableContext.BiosModule[gFitTableContext.BiosModuleNumber].Addres
>s = (UINT32)FitEntry[FitIndex].Address;
>+
>gFitTableContext.BiosModule[gFitTableContext.BiosModuleNumber].Size    =
>*(UINT32 *)&FitEntry[FitIndex].Size[0] * 16;
>+      gFitTableContext.BiosModuleVersion                                     =
>FitEntry[FitIndex].Version;
>+      gFitTableContext.BiosModuleNumber ++;
>+      break;
>+    case FIT_TABLE_TYPE_TPM_POLICY:
>+    case FIT_TABLE_TYPE_TXT_POLICY:
>+      if (FitEntry[FitIndex].Version == 0) {
>+
>gFitTableContext.PortModule[gFitTableContext.PortModuleNumber].Addres
>s = (UINT32)FitEntry[FitIndex].Address;
>+
>gFitTableContext.PortModule[gFitTableContext.PortModuleNumber].Size    =
>(UINT32)(FitEntry[FitIndex].Address >> 32);
>+
>gFitTableContext.PortModule[gFitTableContext.PortModuleNumber].Version
>= FitEntry[FitIndex].Version;
>+
>gFitTableContext.PortModule[gFitTableContext.PortModuleNumber].Type
>= FitEntry[FitIndex].Type;
>+        gFitTableContext.PortModuleNumber ++;
>+        break;
>+      }
>+      // Not Port Configure, pass through
>+    default: // Others
>+
>gFitTableContext.OptionalModule[gFitTableContext.OptionalModuleNumber
>].Address = (UINT32)FitEntry[FitIndex].Address;
>+
>gFitTableContext.OptionalModule[gFitTableContext.OptionalModuleNumber
>].Size    = *(UINT32 *)&FitEntry[FitIndex].Size[0];
>+
>gFitTableContext.OptionalModule[gFitTableContext.OptionalModuleNumber
>].Version = FitEntry[FitIndex].Version;
>+
>gFitTableContext.OptionalModule[gFitTableContext.OptionalModuleNumber
>].Type    = FitEntry[FitIndex].Type;
>+      gFitTableContext.OptionalModuleNumber ++;
>+      break;
>+    }
>+  }
>+
>+  return gFitTableContext.FitEntryNumber;
>+}
>+
>+STATUS
>+FitGen (
>+  IN INTN   argc,
>+  IN CHAR8  **argv
>+  )
>+/*++
>+
>+Routine Description:
>+
>+  Main function for FitGen.
>+
>+Arguments:
>+
>+  argc - Number of command line parameters.
>+  argv - Array of pointers to parameter strings.
>+
>+Returns:
>+  STATUS_SUCCESS - Utility exits successfully.
>+  STATUS_ERROR   - Some error occurred during execution.
>+
>+--*/
>+{
>+  UINT32                      FvRecoveryFileSize;
>+  UINT8                       *FileBuffer;
>+  UINT8                       *FileBufferRaw;
>+  UINTN                       FitEntryNumber;
>+  UINT8                       *FitTableOffset;
>+  STATUS                      Status;
>+  UINT32                      FitTableSize;
>+
>+  BOOLEAN                     IsFv;
>+  UINT8                       *FdFileBuffer;
>+  UINT32                      FdFileSize;
>+
>+  UINT8                       *AcmBuffer;
>+
>+  //
>+  // Step 0: Check FV or FD
>+  //
>+  if (((strcmp (argv[1], "-D") == 0) ||
>+       (strcmp (argv[1], "-d") == 0)) ) {
>+    IsFv = FALSE;
>+  } else {
>+    IsFv = TRUE;
>+  }
>+
>+  //
>+  // Step 1: Read InputFvRecovery.fv data
>+  //
>+  if (IsFv) {
>+    Status = ReadInputFile (argv[1], &FileBuffer, &FvRecoveryFileSize,
>&FileBufferRaw);
>+    if (Status != STATUS_SUCCESS) {
>+      Error (NULL, 0, 0, "Unable to open file", "%s", argv[1]);
>+      goto exitFunc;
>+    }
>+    FdFileBuffer = FileBuffer;
>+    FdFileSize = FvRecoveryFileSize;
>+  } else {
>+    Status = ReadInputFile (argv[2], &FdFileBuffer, &FdFileSize,
>&FileBufferRaw);
>+    if (Status != STATUS_SUCCESS) {
>+      Error (NULL, 0, 0, "Unable to open file", "%s", argv[2]);
>+      goto exitFunc;
>+    }
>+
>+    //
>+    // Get Fvrecovery information
>+    //
>+    FvRecoveryFileSize = GetFvRecoveryInfoFromFd (FdFileBuffer, FdFileSize,
>&FileBuffer);
>+    if ((FvRecoveryFileSize == 0) || (FileBuffer == NULL)) {
>+      Error (NULL, 0, 0, "FvRecovery not found in Fd file!", NULL);
>+      Status = STATUS_ERROR;
>+      goto exitFunc;
>+    }
>+  }
>+
>+  //
>+  // Step 2: Calculate FIT entry number.
>+  //
>+  FitEntryNumber = GetFitEntryNumber (argc, argv, FdFileBuffer, FdFileSize);
>+  if (!gFitTableContext.Clear) {
>+    if (FitEntryNumber == 0) {
>+      Status = STATUS_ERROR;
>+      goto exitFunc;
>+    }
>+
>+    //
>+    // For debug
>+    //
>+    PrintFitData ();
>+
>+    //
>+    // Add 1 more FitEntry as place holder, because we need exclude FIT table
>itself
>+    //
>+    FitEntryNumber++;
>+
>+    //
>+    // Step 3: Get enough space in FvRecovery.fv
>+    //
>+    FitTableOffset = GetFreeSpaceFromFv (FileBuffer, FvRecoveryFileSize,
>FitEntryNumber);
>+    if (FitTableOffset == NULL) {
>+      return STATUS_ERROR;
>+    }
>+    FitTableSize = FitEntryNumber *
>sizeof(FIRMWARE_INTERFACE_TABLE_ENTRY);
>+    FitTableSize += FIT_ALIGNMENT;
>+    FitTableSize &= ~FIT_ALIGNMENT;
>+
>+    CheckOverlap (
>+      MEMORY_TO_FLASH (FitTableOffset, FdFileBuffer, FdFileSize),
>+      FitTableSize
>+      );
>+
>+    //
>+    // Get ACM buffer
>+    //
>+    if (gFitTableContext.StartupAcm.Address != 0) {
>+      AcmBuffer = FLASH_TO_MEMORY(gFitTableContext.StartupAcm.Address,
>FdFileBuffer, FdFileSize);
>+      if ((AcmBuffer < FdFileBuffer) || (AcmBuffer +
>gFitTableContext.StartupAcm.Size > FdFileBuffer + FdFileSize)) {
>+        printf ("ACM out of range - can not validate it\n");
>+        AcmBuffer = NULL;
>+      }
>+
>+      if (AcmBuffer != NULL) {
>+        if (CheckAcm ((ACM_FORMAT *)AcmBuffer,
>gFitTableContext.StartupAcm.Size)) {
>+          DumpAcm ((ACM_FORMAT *)AcmBuffer);
>+        } else {
>+          Status = STATUS_ERROR;
>+          goto exitFunc;
>+        }
>+      }
>+
>+    }
>+
>+    //
>+    // Step 4: Fill the FIT table one by one
>+    //
>+    FillFitTable (FdFileBuffer, FdFileSize, FitTableOffset);
>+
>+    //
>+    // For debug
>+    //
>+    PrintFitTable (FdFileBuffer, FdFileSize);
>+  } else {
>+    printf ("Clear FIT table ...\n");
>+    //
>+    // Step 3: Get FIT table info
>+    //
>+    FitEntryNumber = GetFitEntryInfo (FdFileBuffer, FdFileSize);
>+    if (FitEntryNumber == 0) {
>+      Error (NULL, 0, 0, "No FIT table found", NULL);
>+      return STATUS_ERROR;
>+    }
>+
>+    //
>+    // For debug
>+    //
>+    PrintFitTable (FdFileBuffer, FdFileSize);
>+
>+    //
>+    // Step 4: Clear FIT table
>+    //
>+    ClearFitTable (FdFileBuffer, FdFileSize);
>+    printf ("Clear FIT table Done!\n");
>+  }
>+
>+  //
>+  // Step 5: Write OutputFvRecovery.fv data
>+  //
>+  if (IsFv) {
>+    Status = WriteOutputFile (argv[2], FileBuffer, FvRecoveryFileSize);
>+  } else {
>+    Status = WriteOutputFile (argv[3], FdFileBuffer, FdFileSize);
>+  }
>+
>+exitFunc:
>+  if (FileBufferRaw != NULL) {
>+    free ((VOID *)FileBufferRaw);
>+  }
>+  return Status;
>+}
>+
>+STATUS
>+FitView (
>+  IN INTN   argc,
>+  IN CHAR8  **argv
>+  )
>+/*++
>+
>+Routine Description:
>+
>+  View function for FitGen.
>+
>+Arguments:
>+
>+  argc - Number of command line parameters.
>+  argv - Array of pointers to parameter strings.
>+
>+Returns:
>+  STATUS_SUCCESS - Utility exits successfully.
>+  STATUS_ERROR   - Some error occurred during execution.
>+
>+--*/
>+{
>+  UINT32                      FvRecoveryFileSize;
>+  UINT8                       *FileBuffer;
>+  UINT8                       *FileBufferRaw = NULL;
>+  STATUS                      Status;
>+
>+  //
>+  // Step 1: Read input file
>+  //
>+  Status = ReadInputFile (argv[2], &FileBuffer, &FvRecoveryFileSize,
>&FileBufferRaw);
>+  if (Status != STATUS_SUCCESS) {
>+    Error (NULL, 0, 0, "Unable to open file", "%s", argv[2]);
>+    goto exitFunc;
>+  }
>+
>+  // no -f option, use default FIT pointer offset
>+  if (argc == 3) {
>+    //
>+    // Use default address
>+    //
>+    gFitTableContext.FitTablePointerOffset =
>DEFAULT_FIT_TABLE_POINTER_OFFSET;
>+  } else if (stricmp (argv[3], "-f") == 0) {
>+    if (argc == 5) {
>+      //
>+      // Get offset from parameter
>+      //
>+      gFitTableContext.FitTablePointerOffset = xtoi (argv[3 + 1]);
>+    } else {
>+      Error (NULL, 0, 0, "FIT offset not specified!", NULL);
>+      goto exitFunc;
>+    }
>+  } else {
>+    Error (NULL, 0, 0, "Invalid view option: ", "%s", argv[3]);
>+    goto exitFunc;
>+  }
>+
>+  //
>+  // For debug
>+  //
>+  PrintFitTable (FileBuffer, FvRecoveryFileSize);
>+
>+exitFunc:
>+  if (FileBufferRaw != NULL) {
>+    free ((VOID *)FileBufferRaw);
>+  }
>+  return Status;
>+}
>+
>+int
>+main (
>+  int   argc,
>+  char  **argv
>+  )
>+/*++
>+
>+Routine Description:
>+
>+  Main function.
>+
>+Arguments:
>+
>+  argc - Number of command line parameters.
>+  argv - Array of pointers to parameter strings.
>+
>+Returns:
>+  STATUS_SUCCESS - Utility exits successfully.
>+  STATUS_ERROR   - Some error occurred during execution.
>+
>+--*/
>+{
>+  SetUtilityName (UTILITY_NAME);
>+
>+  //
>+  // Display utility information
>+  //
>+  PrintUtilityInfo ();
>+
>+  //
>+  // Verify the correct number of arguments
>+  //
>+  if (argc >= MIN_VIEW_ARGS && stricmp (argv[1], "-view") == 0) {
>+    return FitView (argc, argv);
>+  } else if (argc >= MIN_ARGS) {
>+    return FitGen (argc, argv);
>+  } else {
>+    Error (NULL, 0, 0, "invalid number of input parameters specified", NULL);
>+    PrintUsage ();
>+    return STATUS_ERROR;
>+  }
>+}
>+
>+unsigned int
>+xtoi (
>+  char  *str
>+  )
>+/*++
>+
>+Routine Description:
>+
>+  Convert hex string to uint
>+
>+Arguments:
>+
>+  str  -  The string
>+
>+Returns:
>+
>+--*/
>+{
>+  unsigned int u;
>+  char         c;
>+  unsigned int m;
>+
>+  if (str == NULL) {
>+    return 0;
>+  }
>+
>+  m = (unsigned int) -1 >> 4;
>+  //
>+  // skip preceeding white space
>+  //
>+  while (*str && *str == ' ') {
>+    str += 1;
>+  }
>+  //
>+  // skip preceeding zeros
>+  //
>+  while (*str && *str == '0') {
>+    str += 1;
>+  }
>+  //
>+  // skip preceeding x/X character
>+  //
>+  if (*str && (*str == 'x' || *str == 'X')) {
>+    str += 1;
>+  }
>+  //
>+  // convert hex digits
>+  //
>+  u = 0;
>+  c = *(str++);
>+  while (c) {
>+    if (c >= 'a' && c <= 'f') {
>+      c -= 'a' - 'A';
>+    }
>+
>+    if ((c >= '0' && c <= '9') || (c >= 'A' && c <= 'F')) {
>+      if (u > m) {
>+        return (unsigned int) -1;
>+      }
>+
>+      u = (u << 4) | (c - (c >= 'A' ? 'A' - 10 : '0'));
>+    } else {
>+      //
>+      // Let application exit immediately
>+      //
>+      Error (NULL, 0, 0, "Hex value is expected!", NULL);
>+      exit (0);
>+      break;
>+    }
>+
>+    c = *(str++);
>+  }
>+
>+  return u;
>+}
>+
>diff --git a/Silicon/Intel/Tools/FitGen/FitGen.h
>b/Silicon/Intel/Tools/FitGen/FitGen.h
>new file mode 100644
>index 0000000000..9bd3f6824b
>--- /dev/null
>+++ b/Silicon/Intel/Tools/FitGen/FitGen.h
>@@ -0,0 +1,48 @@
>+/**@file
>+Definitions for the FitGen utility.
>+
>+Copyright (c) 2010-2019, Intel Corporation. All rights reserved.<BR>
>+SPDX-License-Identifier: BSD-2-Clause-Patent
>+
>+**/
>+
>+#ifndef _FIT_GEN_H
>+#define _FIT_GEN_H
>+
>+#include <stdio.h>
>+#include <stdlib.h>
>+#define PI_SPECIFICATION_VERSION  0x00010000
>+#define EFI_FVH_PI_REVISION       EFI_FVH_REVISION
>+#include <Common/UefiBaseTypes.h>
>+#include <Common/PiFirmwareFile.h>
>+#include <Common/PiFirmwareVolume.h>
>+#include <Guid/PiFirmwareFileSystem.h>
>+#include "EfiUtilityMsgs.c"
>+#include "CommonLib.h"
>+#include "ParseInf.h"
>+#include "FvLib.h"
>+
>+//
>+// Utility Name
>+//
>+#define UTILITY_NAME  "FitGen"
>+
>+//
>+// Utility version information
>+//
>+#define UTILITY_MAJOR_VERSION 0
>+#define UTILITY_MINOR_VERSION 56
>+#define UTILITY_DATE          __DATE__
>+
>+//
>+// The minimum number of arguments accepted from the command line.
>+//
>+#define MIN_VIEW_ARGS   3
>+#define MIN_ARGS        4
>+#define BUF_SIZE        (8 * 1024)
>+
>+#define GETOCCUPIEDSIZE(ActualSize, Alignment) \
>+  (ActualSize) + (((Alignment) - ((ActualSize) & ((Alignment) - 1))) &
>((Alignment) - 1))
>+;
>+
>+#endif
>diff --git a/Silicon/Intel/Tools/FitGen/GNUmakefile
>b/Silicon/Intel/Tools/FitGen/GNUmakefile
>new file mode 100644
>index 0000000000..00a99bb0c7
>--- /dev/null
>+++ b/Silicon/Intel/Tools/FitGen/GNUmakefile
>@@ -0,0 +1,16 @@
>+# @file
>+# GNUmakefile for building the FitGen utility.
>+#
>+# Copyright (c) 2010-2019, Intel Corporation. All rights reserved.<BR>
>+# SPDX-License-Identifier: BSD-2-Clause-Patent
>+#
>+MAKEROOT ?= $(EDK_TOOLS_PATH)/Source/C
>+
>+APPNAME = FitGen
>+
>+OBJECTS = FitGen.o
>+
>+include $(MAKEROOT)/Makefiles/app.makefile
>+
>+LIBS = -lCommon
>+
>diff --git a/Silicon/Intel/Tools/FitGen/Makefile
>b/Silicon/Intel/Tools/FitGen/Makefile
>new file mode 100644
>index 0000000000..fd286b26be
>--- /dev/null
>+++ b/Silicon/Intel/Tools/FitGen/Makefile
>@@ -0,0 +1,17 @@
>+# @file
>+# makefile for building the FitGen utility.
>+#
>+# Copyright (c) 2010-2019, Intel Corporation. All rights reserved.<BR>
>+# SPDX-License-Identifier: BSD-2-Clause-Patent
>+#
>+
>+!INCLUDE $(EDK_TOOLS_PATH)\Source\C\Makefiles\ms.common
>+
>+APPNAME = FitGen
>+
>+LIBS = $(LIB_PATH)\Common.lib
>+
>+OBJECTS = FitGen.obj
>+
>+!INCLUDE $(EDK_TOOLS_PATH)\Source\C\Makefiles\ms.app
>+
>--
>2.18.0.windows.1
>
>
>


-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.

View/Reply Online (#42854): https://edk2.groups.io/g/devel/message/42854
Mute This Topic: https://groups.io/mt/32154338/1813853
Group Owner: devel+owner at edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub  [edk2-devel-archive at redhat.com]
-=-=-=-=-=-=-=-=-=-=-=-





More information about the edk2-devel-archive mailing list